diff options
1120 files changed, 35911 insertions, 8363 deletions
diff --git a/CMakeCPack.cmake b/CMakeCPack.cmake index a27d00004..2495c4476 100644 --- a/CMakeCPack.cmake +++ b/CMakeCPack.cmake @@ -113,6 +113,8 @@ if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") include(Utilities/Release/Cygwin/CMakeLists.txt) endif() + set(CPACK_WIX_UPGRADE_GUID "8ffd1d72-b7f1-11e2-8ee5-00238bca4991") + # Set the options file that needs to be included inside CMakeCPackOptions.cmake set(QT_DIALOG_CPACK_OPTIONS_FILE ${CMake_BINARY_DIR}/Source/QtDialog/QtDialogCPack.cmake) configure_file("${CMake_SOURCE_DIR}/CMakeCPackOptions.cmake.in" diff --git a/CMakeCPackOptions.cmake.in b/CMakeCPackOptions.cmake.in index 47dad49c2..008a102b5 100644 --- a/CMakeCPackOptions.cmake.in +++ b/CMakeCPackOptions.cmake.in @@ -34,7 +34,7 @@ if(CPACK_GENERATOR MATCHES "NSIS") set(CPACK_NSIS_MODIFY_PATH ON) endif() -# include the cpack options for qt dialog if they exisit +# include the cpack options for qt dialog if they exist # they might not if qt was not enabled for the build include("@QT_DIALOG_CPACK_OPTIONS_FILE@" OPTIONAL) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75d372d03..1fbbe08a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -231,7 +231,7 @@ macro (CMAKE_BUILD_UTILITIES) set(KWSYS_USE_Process 1) set(KWSYS_USE_CommandLineArguments 1) set(KWSYS_HEADER_ROOT ${CMake_BINARY_DIR}/Source) - set(KWSYS_INSTALL_DOC_DIR "${CMake_DOC_DEST}") + set(KWSYS_INSTALL_DOC_DIR "${CMAKE_DOC_DIR}") add_subdirectory(Source/kwsys) set(kwsys_folder "Utilities/KWSys") CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE} "${kwsys_folder}") @@ -460,26 +460,27 @@ set(LIBRARY_OUTPUT_PATH "" CACHE INTERNAL # install tree. set(CMAKE_SKIP_RPATH ON CACHE INTERNAL "CMake does not need RPATHs.") -set(CMAKE_DATA_DIR "/share/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}" CACHE STRING +set(CMAKE_DATA_DIR "share/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}" CACHE STRING "Install location for data (relative to prefix).") -set(CMAKE_DOC_DIR "/doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}" CACHE STRING +set(CMAKE_DOC_DIR "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}" CACHE STRING "Install location for documentation (relative to prefix).") -set(CMAKE_MAN_DIR "/man" CACHE STRING +set(CMAKE_MAN_DIR "man" CACHE STRING "Install location for man pages (relative to prefix).") mark_as_advanced(CMAKE_DATA_DIR CMAKE_DOC_DIR CMAKE_MAN_DIR) if(CYGWIN AND EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") # Force doc, data and man dirs to conform to cygwin layout. - set(CMAKE_DOC_DIR "/share/doc/cmake-${CMake_VERSION}") - set(CMAKE_DATA_DIR "/share/cmake-${CMake_VERSION}") - set(CMAKE_MAN_DIR "/share/man") + set(CMAKE_DOC_DIR "share/doc/cmake-${CMake_VERSION}") + set(CMAKE_DATA_DIR "share/cmake-${CMake_VERSION}") + set(CMAKE_MAN_DIR "share/man") # let the user know we just forced these values message(STATUS "Setup for Cygwin packaging") message(STATUS "Override cache CMAKE_DOC_DIR = ${CMAKE_DOC_DIR}") message(STATUS "Override cache CMAKE_DATA_DIR = ${CMAKE_DATA_DIR}") message(STATUS "Override cache CMAKE_MAN_DIR = ${CMAKE_MAN_DIR}") endif() -string(REGEX REPLACE "^/" "" CMake_DATA_DEST "${CMAKE_DATA_DIR}") -string(REGEX REPLACE "^/" "" CMake_DOC_DEST "${CMAKE_DOC_DIR}") +string(REGEX REPLACE "^/" "" CMAKE_DATA_DIR "${CMAKE_DATA_DIR}") +string(REGEX REPLACE "^/" "" CMAKE_DOC_DIR "${CMAKE_DOC_DIR}") +string(REGEX REPLACE "^/" "" CMAKE_MAN_DIR "${CMAKE_MAN_DIR}") if(BUILD_TESTING) include(${CMake_SOURCE_DIR}/Tests/CMakeInstall.cmake) @@ -625,12 +626,12 @@ add_test(SystemInformationNew "${CMAKE_CMAKE_COMMAND}" --system-information -G "${CMAKE_TEST_GENERATOR}" ) # Install license file as it requires. -install(FILES Copyright.txt DESTINATION ${CMake_DOC_DEST}) +install(FILES Copyright.txt DESTINATION ${CMAKE_DOC_DIR}) # Install script directories. install( DIRECTORY Modules Templates - DESTINATION "${CMake_DATA_DEST}" + DESTINATION ${CMAKE_DATA_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ DIRECTORY_PERMISSIONS OWNER_READ OWNER_EXECUTE OWNER_WRITE GROUP_READ GROUP_EXECUTE diff --git a/ChangeLog.manual b/ChangeLog.manual index 134b4aa17..b389d8bdb 100644 --- a/ChangeLog.manual +++ b/ChangeLog.manual @@ -1,3 +1,621 @@ +Changes in CMake 2.8.12.2 (since 2.8.12.1) +------------------------------------------ +Brad King (4): + VS: Map /Fd to ProgramDataBaseFileName for VS 7,8,9 (#14577) + Replace <OBJECT_DIR> rule placeholder consistently (#14667) + VS: Convert include path to backslashes for VS >= 10 + Revert "Ninja: Track configured files so we can regenerate them." + +Rolf Eike Beer (1): + FindOpenMP: fix detecting compilers that do not need any special flag (#14567) + +Ruslan Baratov (1): + Xcode: Fix storyboard view + +Ted Kremenek (1): + CMakeDetermineCompilerId: Fix compiler line match for Xcode 5.1 + +Changes in CMake 2.8.12.1 (since 2.8.12) +---------------------------------------- +Brad King (9): + MSVC: Add /FS flag for cl >= 18 to allow parallel compilation (#14492) + Genex: Reject $<TARGET_FILE:...> for object libraries (#14532) + Check for OBJECT_LIBRARY source files at start of generation + CMP0022: Plain target_link_libraries must populate link interface + Do not export INTERFACE_LINK_LIBRARIES from non-linkable targets + CMP0022: Warn about a given target at most once + Fix summary documentation of INTERFACE_LINK_LIBRARIES + file(GENERATE): Clear internal records between configures + cmake: Validate -E cmake_automoc argument count (#14545) + +Modestas Vainius (1): + Fix spelling in INTERFACE_LINK_LIBRARIES documentation (#14542) + +Stephen Kelly (5): + CMP0022: Output link interface mismatch for static library warning + Don't add invalid content to static lib INTERFACE_LINK_LIBRARIES. + CMP0022: Add unit test for null pointer check and message. + CMP0022: Add test for target_link_libraries plain signature + Automoc: Add directory-level COMPILE_DEFINITIONS to command line (#14535) + +Vladislav Vinogradov (1): + FindCUDA: Fix NPP library search for CUDA 5.5 + +Changes in CMake 2.8.12 (since 2.8.12-rc4) +------------------------------------------ +Brad King (4): + Xcode: Fix test architecture selection for Xcode >= 5 + Xcode: Teach Tests/BuildDepends to allow LINK_DEPENDS_NO_SHARED failure + Xcode: Drop XCODE_DEPEND_HELPER for Xcode >= 5 + Xcode: Fix OBJECT library support for Xcode 5 (#14254) + +Stephen Kelly (1): + Genex: Fix processing multiple include directories for relative paths + +Changes in CMake 2.8.12-rc4 (since 2.8.12-rc3) +---------------------------------------------- +Brad King (8): + VS: Future-proof Intel project format selection + MSVC: Drop /link from executable link lines with Ninja + FindCUDA: Always list custom command outputs in their targets + FindPNG: Honor old PNG_LIBRARY if provided (#14398) + FindHDF5: Fix regression in per-configuration library selection + bash-completion: Future-proof --help-*-list "cXXXX version" filtering + OS X: Search system SDKs for frameworks + Use first custom command for the same output (#14446) + +Patrick Gansterer (3): + MSVC: Fix version test for linking corelibc on Windows CE (#14420) + MSVC: Fix WinCE arch family preprocessor symbol (#14436) + VS: Use version-specific subsystem for WinCE compiler id (#14440) + +Rolf Eike Beer (1): + bootstrap: try better workaround for builds on Linux/HPPA + +Stephen Kelly (3): + Add differing target property content to policy CMP0022 warning + Fix CMP0022 warning when no old-style property is set + genex: Fix preprocessing with incomplete content (#14410). + +Changes in CMake 2.8.12-rc3 (since 2.8.12-rc2) +---------------------------------------------- +Robert Maynard (1): + cmMakefile: Do not track CMake temporary files. + +Changes in CMake 2.8.12-rc2 (since 2.8.12-rc1) +---------------------------------------------- +Brad King (2): + Fix RunCMake.Configure test expectation newline matching + Clean up install rules of CMake itself (#14371) + +Clinton Stimpson (1): + OSX: Allow an empty INSTALL_NAME_DIR to override MACOSX_RPATH. + +Eric Bélanger (1): + FindImageMagick: Find libraries named with HDRI support (#14348) + +Raphael Kubo da Costa (1): + FindTCL: Add BSD paths for Tcl/Tk 8.6 + +Robert Maynard (2): + VS: Generate ToolsVersion matching each VS version + cmMakefile: Do not track configured files known to be temporary + +Rolf Eike Beer (1): + CheckC*CompilerFlag: add documentation what to expect from a positive result + +Stephen Kelly (6): + Fix OLD behavior of CMP0021. + try_compile: Extract IMPORTED targets from LINK_DEPENDENT_LIBRARIES + try_compile: Extract IMPORTED targets from INTERFACE_LINK_LIBRARIES + Genex: Fix evaluation of MAP_IMPORTED_CONFIG_<CONFIG> + Fix some whitespace errors in docs. + Normalize system directories from the interface target property + +Yury G. Kudryashov (1): + CPack: Fix a typo in documentation + +Zack Galbreath (1): + CTest: Fix GTM coverage parsing line offset bug + +Changes in CMake 2.8.12-rc1 (since 2.8.11.2) +-------------------------------------------- +Adam J. Weigold (1): + CPackWIX: Add support for custom WiX templates + +Alex Neundorf (12): + CMakeSystem: include toolchain file after setting CMAKE_HOST_ (#13796) + Add support files for C, C++ and ASM for the IAR toolchain. + Add regexps for the IAR toolchain to the vendor list. + Add IAR to the CMakeDetectC(XX)CompilerID.c(pp).in + cmake-gui: use shortcut F only for "Find in Output" + Eclipse: fix #14204 and #14205: no file links to directories + automoc: add a global AUTOMOC_TARGETS_FOLDER property + install: do not strip dll import libraries (#14123) + ExportTargets: add one more comment to the generated file. + Add documentation for the --graphviz support + graphvizoptions: add copyright notice + add macros cmake_print_properties() and cmake_print_variables() + +Alexander Mohr (1): + VS: Detect MSVC compiler id on ARM toolchain + +Andreas Mohr (10): + Fix spelling and typos (affecting users) + Fix spelling and typos (affecting binary data / module messages) + Fix spelling and typos (non-binary) + Fix spelling and typos (product names) + FindwxWidgets: add DOC strings with usual style + Explain distribution of Win9x binary on all Windows versions. + VS10: add detailed comment about MIDL processing + Docs: Update description of CMAKE_(BUILD_TYPE|CONFIGURATION_TYPES) + Docs: Clarify that CMAKE_*_(PREFIX|SUFFIX) affect filenames + Docs: Clarify wording "flag used" => "flag (to|will) be used" + +Ben Boeckel (12): + set_property: Do not remove a property when APPENDing nothing + Tests/RunCMake: Document stripping of expected output + export: Error when exporting a target without a language + variable_watch: Store client data as pointers + variable_watch: Add a deleter for the client data + variable_watch: Match client_data when finding duplicates + variable_watch: Allow specifying the data to match in RemoveWatch + variable_watch: Prevent making extra entries in the watch map + variable_watch: Fix a typo in the error message + variable_watch: Don't share memory for callbacks + variable_watch: Check newValue for NULL + variable_watch: Add test for watching a variable multiple times + +Bill Hoffman (1): + Do not set CMAKE_MATCH_ variables when not neeeded + +Bjoern Thiel (1): + SelectLibraryConfigurations: Fix for cached <base>_LIBRARY + +Brad King (91): + VS: Separate compiler and linker PDB files (#11899, #14062) + MSVC: Invoke 'link' directly for executables + Ninja: Fix OBJECT_DIR placeholder path conversion + VS 10: Escape ; as %3B in preprocessor definitions (#14073) + CTest: Simplify ctest_* command source/build dir lookup + get_filename_component: Add explicit unit tests + get_filename_component: Add DIRECTORY option (#14091) + Xcode: Use explicitFileType to mark source types (#14093) + Check{C,CXX}CompilerFlag: Test using C locale (#14102) + Windows: Search '/' prefix only when cross compiling (#10994) + Recognize ld with toolchain prefix (#13960) + VS: Always initialize CMAKE_CONFIGURATION_TYPES in IDE generators + Begin post-2.8.11 development + Sanitize linker name to parse implicit link line (#14154) + VS: Allow /Fa to set AssemblerListingLocation (#14153) + Tests/IncludeDirectories: Avoid shared library with no symbols + if: Add test for IS_DIRECTORY + try_compile: Add test for bad call error cases + try_compile: Refactor argument processing + variable_watch: Add test for MODIFIED_ACCESS report + bootstrap: Compile KWSys SystemTools with UTIME(S|NSAT) values + variable_watch: Remove leftover debugging code (#14187) + variable_watch: Print accesses as "CMake Debug Log" messages + Docs: Clarify CMAKE_PARENT_LIST_FILE (#14194) + get_filename_component: Test ABSOLUTE of .. after root component + try_compile: Add signature to allow multiple SOURCES + enable_language: Clarify documentation + Split cmBootstrapCommands.cxx into two sources + Document CMAKE_INSTALL_PREFIX in CMAKE_SYSTEM_PREFIX_PATH + cmake: Document "-E tar" support for .zip (#14225) + FindBoost: Clarify failure on missing 'static' libs (#14235) + CMakeDetermineVSServicePack: Improve documentation + CMakeDetermineVSServicePack: Add VS 11 update 1 and 2 (#14239) + Document ENV syntax as a "variable" (#14245) + Embarcadero: Use response files only for includes, objects, and libs + Escape target flags taken from COMPILE_OPTIONS + Refactor target COMPILE_OPTIONS and COMPILE_FLAGS handling + CMakeDetermineVSServicePack: Add VS 11 update 3 + Document removal of 'register' from flex/bison output + VS12: Find proper MSBuild for VSProjectInSubdir test + Fortran: Use explicit type in Fortran 90 check + project: Document top-level CMakeLists.txt requirement + ExternalProject: Document multiple COMMAND lines + include: Clarify variable access scope for included file + VS: Fix /MAP:mapfile flag mapping (#14282) + cmake: On configure error suggest looking at CMake*.log files + try_compile: Escape CMAKE_<lang>_FLAGS in test projects (#14268) + try_compile: Add COPY_FILE_ERROR option to capture failure + FindPNG: Add versioned library names for 1.6 (#14289) + cmake: Fix resource leak reported by cppcheck + VS,Xcode: Drop incorrect legacy dependency trace (#14291) + OS X: Add copyright notices to Darwin-*-Fortran.cmake + VS: Avoid leaking child process output back to IDE (#14266) + Fix ExportImport test cmp0022NEW build on Watcom + add_test: Document test name restrictions (#14298) + UseJava: Update notice of copyright by Kitware + add_custom_command: Manage backtrace memory correctly (#14299) + Teach compiler ABI check to tolerate try_compile COPY_FILE failure + Test COMPILE_DEFINITIONS target property get/set/get round-trip + Check*CompilerFlag: Document use of CMAKE_REQUIRED_DEFINITIONS (#14309) + sha2: Avoid type-punned pointer dereference (#14314) + VS 6: Tell BuildDepends test to tolerate ninjadep failure + cmMakefile: Do not track configured files known to be temporary + libarchive: Update README-CMake.txt for new snapshot + libarchive: Include cm_zlib.h to get zlib used by CMake + libarchive: Silence API deprecation warnings + libarchive: Avoid struct init with variable + libarchive: Remove build options not used by CMake + libarchive: Backport to CMake 2.8.2 + VS10: Honor user-specified /SUBSYSTEM: flag (#14326) + VS10: Escape include paths in XML project files (#14331) + OS X: Search for SDK based on deployment target (#14324) + bootstrap: Do not suppress CMAKE_OSX_SYSROOT if CFLAGS have -isysroot (#14324) + OS X: Enable command-line build without tools in PATH + VS 6,7: Refactor local generators to avoid GetSourceFileWithOutput + cmake-gui: Fix build rules for Qt5 on Windows + Include cmMakefile.h before cm*Lexer.h to get stdint.h first + Skip CTestLimitDashJ test on Borland + Add RunCMake.Syntax test to cover argument parsing + cmListFileLexer: Fix line number after backslash in string + cmListFileLexer: Split normal and legacy unquoted arguments + cmListFileArgument: Generalize 'Quoted' bool to 'Delimeter' enum + Add RunCMake.Syntax test cases for command invocation styles + cmListFileCache: Convert CMake language parser to class + Warn about arguments not separated by whitespace + Warn about unquoted arguments that look like long brackets + cmListFileLexer: Modify flex output to avoid Borland warning + Cygwin: Avoid legacy warnings in RunCMake.* tests + Update version introducing CMP0021, CMP0022, and CMP0023 + OS X: Do not default to non-existent deployment target SDK + Do not warn about left paren not separated by a space + +Christian Maaser (1): + VS: Add support for .NET target framework version + +Clinton Stimpson (12): + Improve documentation for CPACK_PACKAGE_INSTALL_REGISTRY_KEY. + Refactor how bundles and frameworks are supported. + Xcode: Add support for shared library versioning + OS X: Fix getting of CFBundle LOCATION property. + OS X: Add RPATH support for Mac. + Xcode: Add rpath support in Xcode generator. + OS X: Add support for @rpath in export files. + OS X: Add test for rpaths on Mac. + OS X: Improvements for getting install name of dylib. + OS X: Enable rpath support on Mac OS X when find_library() is used. + OS X: Fix regression handling frameworks for Ninja + OS X: If necessary, use xcrun to help find otool used to query install names. + +Cédric OCHS (1): + Xcode: Support XCODE_ATTRIBUTE_ with [variant=<config>] (#12532) + +Daniele E. Domenichelli (15): + FindGTK2: Move check for pangocairo in gtk module + FindGTK2: Detect gthread library + FindFreetype: Detect Freetype installed by GtkMM installer for win + FindGTK2: Do not fail on MSVC11 if vc100 libraries are available + FindGTK2: Add GTK2_DEFINITIONS variable + SelectLibraryConfigurations: Do not cache the _LIBRARY variable + SelectLibraryConfigurations: Use -NOTFOUND instead of copying the vars + FindGTK2: Use GTK_XXX_LIBRARY_DEBUG libraries in debug mode + FindGTK2: Append _LIBRARY to var name in _GTK2_FIND_LIBRARY + FindGTK2: Append _INCLUDE_DIR to var name in _GTK2_FIND_INCLUDE_DIR + FindGTK2: Update local changelog + FindGTK2: Remove GTK2_SKIP_MARK_AS_ADVANCED option + FindGTK2: gthread-2.0 folder does not exist + FindGTK2: Detect gmodule library + FindGTK2: Detect pangoft2 and pangoxft libraries + +David Coppa (1): + OpenBSD: Enable ELF parsing and editing (#14241) + +David Golub (1): + CPack/NSIS: Obtain path from which to uninstall from registry (#14124) + +Eric NOULARD (5): + Add support for componentized USER spec file + CPackRPM add mechanism to remove path from generated list of file in RPM spec. + CPackRPM add /usr/lib64 to the list of builtin to-be-excluded path + CPackRPM protect '@' character in filename processed in the spec file. + CPackRPM make the changelog line conform to expected format + +Fredrik Axelsson (1): + CPackWIX: Handle CPACK_PACKAGE_EXECUTABLES (#13967) + +Funda Wang (1): + FindImageMagick: Find v6 include dir (#14174) + +Graham Markall (2): + OS X: Add Fortran library version flags (#14249) + UseJava: Pass sources to javac using response file (#13028) + +Gregoire Lejeune (1): + Allow using Java in a cross-compilation toolchain + +Ian Monroe (2): + Ninja: use cd /D to set directory on Windows + CPackWIX: Fix MSI package layout regression from parent + +Igor Murzov (2): + bash-completion: Add -S,-SP options arguments completion + bash-completion: Fix/improve generator names extraction + +Jack O'Connor (1): + Eclipse: Add a missing space in the documentation + +Jason Spiro (1): + MinGW: Find mingw32-make included with Code::Blocks IDE (#14302) + +John Farrier (2): + VS: Add Windows Forms Support + VS: Add VS_GLOBAL_ROOTNAMESPACE target property + +Jonas Andersen (1): + VS: Add Resx configuration to the vcxproj file + +LibArchive Upstream (1): + libarchive 3.1.2 (reduced) + +Marc Bartholomaeus (4): + cmake-gui: Add search functions for Output window (#9733) + cmake-gui: Add search functions to the context menu of the Output widget + cmake-gui: Change shortcut of the search field from Ctrl-F to Alt-E + cmake-gui: Add function for going to next error message in Output window + +Marcel Loose (1): + FindCUDA: Remove duplicate entries from INCLUDE_DIRECTORIES. + +Marius Schamschula (1): + FindX11: Search in /opt/X11 for OS X 10.8 (#14232) + +Mathias Gaunard (1): + FindCUDA: CUDA_COMPUTE_BUILD_PATH uses relative paths to binary dir. + +Matt McCormick (1): + ExternalProject: Allow blank SVN_USERNAME/SVN_PASSWORD (#14128) + +Matthew Bentham (1): + Xcode: Honor CMAKE_(MODULE|SHARED)_LINKER_FLAGS_<CONFIG> (#14161) + +Matthew Woehlke (3): + UseJava.cmake: fully use cmake_parse_arguments in add_jar + FindProtobuf: also find pthread + UseJava.cmake: document add_jar compat shim + +Nicolas Despres (1): + Optimize custom command full-path dependency lookup + +Nils Gladitz (1): + Add cmake_host_system_information command + +Patrick Gansterer (20): + Add option to use stdout/stderr of original terminal in cmake --build + Unify the way the flags of a static library are read + Add support for CMAKE_STATIC_LINKER_FLAGS + Add CMAKE_STATIC_LINKER_FLAGS to CMakeCommonLanguageInclude + Add documentation for the missing CMAKE_*_LINKER_FLAGS_* variables + Add additonal tests for the linker flags + VS6: Add handling of CMAKE_*_LINKER_FLAGS_<CONFIG> variables + VS6: Hardcode id_machine_6 for compiler detection + VS10: Do not set the TargetMachine when detecting the compiler + VS: Set CMAKE_VS_PLATFORM_NAME for VS7 and VS71 too + VS: Replace ArchitectureId with PlatformName + VS12: Remove duplicated overload of UseFolderProperty() + Fix detection of WinCE SDKs with 64bit verion of CMake + VS: Unify how the name of the generator is specified + VS10: Add support for assembler code (#11536) + WIN: Use COFF file header header for architecture detection (#14083) + Improve const-correctness in cmVisualStudioGeneratorOptions + Fix setting of the entry point symbol for Windows CE (#14088) + Add support for new Windows CE compiler + VS11: Add support for Windows CE SDKs + +Paul Kunysch (1): + CTest: Add test for running many tests in parallel + +Pavel Shramov (1): + cmDependsC: Collapse relative include paths + +Petr Kmoch (5): + Add projectDir parameter to GenerateBuildCommand + VS: Create parser for Visual Studio .sln files + VS: Use .sln parser to build targets in subdirs with msbuild (#13623) + VS: Add test for building MSBuild project in subdir + ctest_build: Pass projectDir to GenerateBuildCommand + +Reid Kleckner (1): + Ninja: Make cmcldeps depfile output more consistent with 'ninja -t msvc' + +Richard Ulrich (3): + CPackWIX: Handle multiple shortcuts in the start menu + CPackWIX: Add option to specify the language(s) of the installer + CMakeCPack: Provide an upgrade guid for WiX + +Robert Maynard (9): + cmMakefile: Refactor AddCMakeDependFile and AddCMakeOutputFile. + Ninja: Track configured files so we can regenerate them. + cmMakefile: Track configured files so we can regenerate them (#13582) + Add a test to expose a bug with add_custom_command and ninja. + Ninja: GlobalNinjaGenerator WriteBuild and WritePhonyBuild non static + Ninja: Custom Command file depends don't need to exist before building + FindCUDA: Search for libraries in <prefix>/lib/<arch>/nvidida-current. + Ninja: Properly convert all paths to unix style before we do set intersection. + Ninja: Update BuildDepends test to verify cmcldeps depfiles. + +Robin Lee (1): + FindOpenSSL: Fix spelling of CMAKE_CROSSCOMPILING (#14075) + +Rolf Eike Beer (25): + FindOpenGL: simplify OS selection code + FindOpenGL: require headers to be found on non-Windows platforms (#13746) + Tests: create output files for all memory checkers + CTest: use an output file for Valgrind (#14110) + CTest: remove unreachable code and CTestTestMemcheckUnknown test + Tests: remove code duplication in CTestTestMemCheck tests + Tests: verify that memory checker output files are always present + CTest: drop suppression for gcc 2.9.6 errors from default Valgrind flags + Tests: add test for non-existent Valgrind suppression file + CTest: fix comment documenting cmBoundsCheckerParser class + Tests: add a test with custom options passed to valgrind + CTest: make sure never to report negative test times (#14132) + Doc: fix example for FAIL_REGULAR_EXPRESSION + CTest: break after first regex match on output + Tests: ignore Guard Malloc messages in MemChecker tests + CTest: avoid useless changing of directory + Tests: fix build of dummy memtester on AIX + wizard: fix warnings + wizard: simplify control flow + cmTarget: drop the unused local typedef LinkLine + Tests: ignore GuardMalloc messages on all Apple build, not just XCode ones + replace string(... MATCHES "^const$) with string(... STREQUAL "const") + Revert "CTest: fix pre and post test commands with spaces" (#13887) + FindPNG: improve library detection (#14301) + CTest: create one output file per memcheck (#14303) + +Sean McBride (1): + Remove some uses of obsolete 'register' storage specifier + +Sebastian Leske (1): + Document CMAKE_<LANG>_FLAGS variable (#14305) + +Stephen Kelly (126): + Make the QtAutomoc test compile with either Qt 4 or Qt 5 + Add a test for Qt5Automoc + Remove an endif() followed by an if() for the same condition. + Fix some copyastos in the DetermineRCCompiler file. + Test transitive includes from setting the LINK_LIBRARIES property. + Test the use of target transitive compile definitions with moc. + Fix handling of commas in arbitrary content in genexes. + Fix style. + Remove unused marker for a variable which is now used. + Extract the ProcessArbitraryContent method. + Rename the method determining if a genex accepts arbitrary content. + Make it possible for any genex to have arbitrary content at the end. + Add the JOIN generator expression. + Test that linking using the debug keyword to tll works. + automoc: Read target defines unconditionally + Remove unused typedef. + Fix brace indentation. + Add EXPORT_NAME property. + Remove unused vector population. + Sublime: Honor source-level COMPILE_FLAGS property + Docs: cmake -G selects a "build system" generator + Recognize shared library files with a numerical suffix + FindQt4: Fix QUIET failure with Qt 5 but not Qt 4 + Error on relative path in INCLUDE_DIRECTORIES target property. + include_directories: Fix handling of empty or space-only entries + CTest: Read CTEST_PARALLEL_LEVEL from environment + string: Add MAKE_C_IDENTIFIER subcommand + GenerateExportHeader: Add newlines to separate the compiler output. + GenerateExportHeader: Allow use of of this macro with MODULEs. + file: Add GENERATE command to produce files at generate time + Tests/Module/GenerateExportHeader: Test exported free-function + Add $<LINK_LANGUAGE> generator expression + GenerateExportHeader: Generate only C identifiers as defines + Tests/CompileDefinitions: Avoid spaces in defines on VS 6 + Use the qt5::moc imported target instead of a variable. + QtAutomoc: Get the Qt version through the target link interface + Fix indentation. + VS6: Rename some variables to correspond to config values. + Add cmLocalGenerator::GetCompileOptions. + Add <LANG>_COMPILER_ID generator expressions. + cmTarget: Rename struct to be more re-usable. + cmTarget: Rename LinkInterfaceIncludeDirectoriesEntries + Add COMPILE_OPTIONS target property. + Add target_compile_options command. + Introduce target property <LANG>_VISIBILITY_PRESET + Add a COMPILE_OPTION for a VISIBILITY_INLINES_HIDDEN target property. + Qt4Macros: Allow specifying a TARGET in invokations of macros. + Introduce add_compile_options command. + Remove unused cmAddDefinitionsCommand::ParseDefinition method. + Add some spaces to the INCLUDE_DIRECTORIES documentation. + CLI: Suppress the unused warning if the key value pair is cached. + Use --sysroot when cross compiling. + Add missing 'seen' check for evaluating COMPILE_OPTIONS. + Find targets in INTERFACE_COMPILE_OPTIONS when exporting for try_compile. + Use a preprocessor loop to manage the valid transitive properties. + Generate INTERFACE_COMPILE_OPTIONS on export. + Genex: Fix indentation in docs. + cmSystemTools: Fix typo in comment. + Style: Don't put an else after a return. + Add compiler target compile options. + QtAutomoc: Fix handling of list separator for compile definitions. + QtAutomoc: Use config-dependent compile definitions and includes. + De-duplicate version comparison code. + Add generator expressions for version comparision. + Don't run the WarnUnusedCliUnused test on Windows. + Add whitespace after colons in error messages. + Add missing return after error report. + Genex: Make LINK_LANGUAGE report an error when evaluating link libraries. + Genex: Extend EvaluatingLinkLibraries to also check the top target name. + Genex: Report error if a target file is needed to evaluate link libraries. + Add generator expressions for compiler versions. + Split the GeneratorExpression test into a third part. + Remove unused variable. + Add Target API to determine if an include is a system include. + Store system include directories in the cmTarget. + Extend the cmTargetPropCommandBase interface property handling. + Add a SYSTEM parameter to target_include_directories (#14180) + Add entire link interface transitive closure as target depends. + Test non-IMPORTED libraries in the INTERFACE of IMPORTED libraries. + GenexEval: Add abstracted access to link interface for a target. + Introduce the LINK_ONLY generator expression. + Introduce the INTERFACE_LINK_LIBRARIES property. + Export: Generate INTERFACE_LINK_LIBRARIES property on targets. + TLL: Don't populate old link interface if CMP0022 is NEW. + Overload cmLocalGenerator::AppendDefines to add a list. + Add an overload of cmIDEOptions::AddDefines taking a vector of strings. + Refactor cmTarget::GetCompileDefinitions to use an out-vector, not a string. + Document some variables for deprecation control. + Genex: Make CMP0021 and CMP0022 usable with TARGET_POLICY + Revert "Use --sysroot when cross compiling." + Add target property debugging for COMPILE_DEFINITIONS + Mark qt4_use_modules and qt4_automoc as obsolete. + Add the INTERFACE_SYSTEM_INCLUDE_DIRECTORIES target property. + Don't add trailing whitespace to error message. + Remove TODO to uniq COMPILE_OPTIONS + Remove the LINK_LANGUAGE generator expression. + Genex: Fix $<CONFIG> with IMPORTED targets and multiple locations. + FindQt4: Don't use Qt component _FOUND vars before they're defined (#14286) + Add a convenient way to add the includes install dir to the INTERFACE. + Use linked frameworks as a source of include directories. + target_link_libraries: Add PUBLIC/PRIVATE/INTERFACE keyword signature + FindQt4: Re-add QAxServer to the QT_MODULES. + FindQt4: Populate the INTERFACE_LINK_LIBRARIES of IMPORTED targets. + Genex: Allow relative paths in INSTALL_INTERFACE. + cmTarget: Fix property name typo in docs. + Docs: Document file(GENERATE) CONDITION as optional. + Qt4Macros: Remove unneeded generate CONDITION. + Qt4Macros: Remove undefined varible use. + Qt4Macros: Simplify some variable population. + Docs: Document existing target property debugging options. + Docs: Trim trailing whitespace in generated doc. + Docs: Generalize and de-duplicate VISIBILITY_PREFIX docs. + Docs: Document variables for default visibility values. + Export: Fix typo of LINK_INTERFACE_LIBRARIES. + cmTarget: Remove duplicates when printing traces of tll signatures + cmTarget: Fix iface libraries and languages for static libraries. + Genex: Disallow LINKER_LANGUAGE only when used on a static library. + install: Remove error condition using INCLUDES DESTINATION without EXPORT. + Fix crash on export of target with empty INTERFACE_INCLUDE_DIRECTORIES. + Allow target commands to be invoked with no items (#14325). + Docs: Fix typo in CMAKE_DEBUG_TARGET_PROPERTIES + cmTarget: Add NAME property + Export: Process generator expressions from INCLUDES DESTINATION. + Add the ALIAS target concept for libraries and executables. + Revert "Add compiler target compile options." + Genex: Fix segfault when parsing ends with parameter expectation. + +Vadim Zhukov (1): + Add cmake_reset_check_state() macro + +Victor Zverovich (1): + Use GmakeErrorParser instead of deprecated MakeErrorParser (fixes bug 0013699) + +Yichao Yu (1): + variable_watch: Add missing string enumeration entry (#14188) + +Ömer Fadıl USTA (3): + ccmake: Add missing initializers reported by cppcheck + libarchive: Fix free() order to avoid accessing freed memory + cmcurl: Fix resource leak reported by cppcheck + Changes in CMake 2.8.11.2 (since 2.8.11.1) ------------------------------------------ Alex Neundorf (1): diff --git a/Docs/CMakeLists.txt b/Docs/CMakeLists.txt index a5e91c9d1..34090d234 100644 --- a/Docs/CMakeLists.txt +++ b/Docs/CMakeLists.txt @@ -1,4 +1,3 @@ -string(REGEX REPLACE "^/(.*)" "\\1" REL_CMAKE_DATA_DIR "${CMAKE_DATA_DIR}") -install(FILES cmake-help.vim cmake-indent.vim cmake-syntax.vim DESTINATION ${REL_CMAKE_DATA_DIR}/editors/vim) -install(FILES cmake-mode.el DESTINATION ${REL_CMAKE_DATA_DIR}/editors/emacs) +install(FILES cmake-help.vim cmake-indent.vim cmake-syntax.vim DESTINATION ${CMAKE_DATA_DIR}/editors/vim) +install(FILES cmake-mode.el DESTINATION ${CMAKE_DATA_DIR}/editors/emacs) add_subdirectory (bash-completion) diff --git a/Docs/bash-completion/CMakeLists.txt b/Docs/bash-completion/CMakeLists.txt index 592b71e93..c0a88999e 100644 --- a/Docs/bash-completion/CMakeLists.txt +++ b/Docs/bash-completion/CMakeLists.txt @@ -5,4 +5,4 @@ # add symlinks to the files in appropriate places # /etc/bash_completion.d/ # DATADIR/completions (may be /usr/share/<package>/completions -install(FILES cmake cpack ctest DESTINATION ${REL_CMAKE_DATA_DIR}/completions) +install(FILES cmake cpack ctest DESTINATION ${CMAKE_DATA_DIR}/completions) diff --git a/Docs/bash-completion/cmake b/Docs/bash-completion/cmake index 59b565ac0..59e02987b 100644 --- a/Docs/bash-completion/cmake +++ b/Docs/bash-completion/cmake @@ -100,21 +100,23 @@ _cmake() return ;; -G) - # FIXME: doesn't work properly local IFS=$'\n' + local quoted + printf -v quoted %q "$cur" COMPREPLY=( $( compgen -W '$( cmake --help 2>/dev/null | sed -n \ - "/^.*[^ ].*= Generates/{s|^ *\(.*[^ ]\) *= Generates.*$|\1|;s| |\\\\ |g;p}" \ - 2>/dev/null )' -- "$cur" ) ) + -e "1,/^Generators/d" \ + -e "/^ *[^ =]/{s|^ *\([^=]*[^ =]\).*$|\1|;s| |\\\\ |g;p}" \ + 2>/dev/null )' -- "$quoted" ) ) return ;; --help-command) COMPREPLY=( $( compgen -W '$( cmake --help-command-list 2>/dev/null| - tail -n +2 )' -- "$cur" ) ) + grep -v "^cmake version " )' -- "$cur" ) ) return ;; --help-module) COMPREPLY=( $( compgen -W '$( cmake --help-module-list 2>/dev/null| - tail -n +2 )' -- "$cur" ) ) + grep -v "^cmake version " )' -- "$cur" ) ) return ;; --help-policy) @@ -124,12 +126,12 @@ _cmake() ;; --help-property) COMPREPLY=( $( compgen -W '$( cmake --help-property-list \ - 2>/dev/null | tail -n +2 )' -- "$cur" ) ) + 2>/dev/null | grep -v "^cmake version " )' -- "$cur" ) ) return ;; --help-variable) COMPREPLY=( $( compgen -W '$( cmake --help-variable-list \ - 2>/dev/null | tail -n +2 )' -- "$cur" ) ) + 2>/dev/null | grep -v "^cmake version " )' -- "$cur" ) ) return ;; esac diff --git a/Docs/bash-completion/cpack b/Docs/bash-completion/cpack index a0c1f8375..9ab604839 100644 --- a/Docs/bash-completion/cpack +++ b/Docs/bash-completion/cpack @@ -8,8 +8,8 @@ _cpack() case "$prev" in -G) COMPREPLY=( $( compgen -W '$( cpack --help 2>/dev/null | - grep "^ .*= .*" 2> /dev/null | grep -v "^ -" 2>/dev/null | - cut -d" " -f 3 )' -- "$cur" ) ) + sed -e "1,/^Generators/d" -e "s|^ *\([^ ]*\) .*$|\1|" \ + 2>/dev/null )' -- "$cur" ) ) return ;; -C) @@ -20,7 +20,7 @@ _cpack() -D) [[ $cur == *=* ]] && return # no completion for values COMPREPLY=( $( compgen -W '$( cpack --help-variable-list \ - 2>/dev/null | tail -n +2 )' -S = -- "$cur" ) ) + 2>/dev/null | grep -v "^cpack version " )' -S = -- "$cur" ) ) compopt -o nospace return ;; @@ -38,12 +38,12 @@ _cpack() ;; --help-command) COMPREPLY=( $( compgen -W '$( cpack --help-command-list 2>/dev/null| - tail -n +2 )' -- "$cur" ) ) + grep -v "^cpack version " )' -- "$cur" ) ) return ;; --help-variable) COMPREPLY=( $( compgen -W '$( cpack --help-variable-list \ - 2>/dev/null | tail -n +2 )' -- "$cur" ) ) + 2>/dev/null | grep -v "^cpack version " )' -- "$cur" ) ) return ;; esac diff --git a/Docs/bash-completion/ctest b/Docs/bash-completion/ctest index 9707f6269..25cb99841 100644 --- a/Docs/bash-completion/ctest +++ b/Docs/bash-completion/ctest @@ -54,7 +54,7 @@ _ctest() return ;; -S|--script|-SP|--script-new-process) - # FIXME ? + _filedir '@(cmake|ctest)' return ;; --interactive-debug-mode) @@ -63,7 +63,7 @@ _ctest() ;; --help-command) COMPREPLY=( $( compgen -W '$( ctest --help-command-list 2>/dev/null| - tail -n +2 )' -- "$cur" ) ) + grep -v "^ctest version " )' -- "$cur" ) ) return ;; esac diff --git a/Modules/AutomocInfo.cmake.in b/Modules/AutomocInfo.cmake.in index 640bf70a0..9cff735fb 100644 --- a/Modules/AutomocInfo.cmake.in +++ b/Modules/AutomocInfo.cmake.in @@ -6,10 +6,9 @@ set(AM_MOC_OPTIONS @_moc_options@) set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/") -set(AM_QT_MOC_EXECUTABLE "@QT_MOC_EXECUTABLE@") +set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/") set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/") -set(AM_QT_VERSION_MAJOR "@QT_VERSION_MAJOR@" ) -set(AM_Qt5Core_VERSION_MAJOR "@Qt5Core_VERSION_MAJOR@" ) +set(AM_QT_VERSION_MAJOR "@_target_qt_version@") set(AM_TARGET_NAME @_moc_target_name@) set(AM_RELAXED_MODE "@_moc_relaxed_mode@") diff --git a/Modules/CMakeBackwardCompatibilityC.cmake b/Modules/CMakeBackwardCompatibilityC.cmake index e3b6c823e..4783d68cd 100644 --- a/Modules/CMakeBackwardCompatibilityC.cmake +++ b/Modules/CMakeBackwardCompatibilityC.cmake @@ -55,7 +55,7 @@ if(NOT CMAKE_SKIP_COMPATIBILITY_TESTS) TEST_BIG_ENDIAN(CMAKE_WORDS_BIGENDIAN) include (FindX11) - if("${X11_X11_INCLUDE_PATH}" MATCHES "^/usr/include$") + if("${X11_X11_INCLUDE_PATH}" STREQUAL "/usr/include") set (CMAKE_X_CFLAGS "" CACHE STRING "X11 extra flags.") else() set (CMAKE_X_CFLAGS "-I${X11_X11_INCLUDE_PATH}" CACHE STRING diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in index c25df0cb5..66a558265 100644 --- a/Modules/CMakeCCompilerId.c.in +++ b/Modules/CMakeCCompilerId.c.in @@ -160,10 +160,9 @@ # define COMPILER_ID "ADSP" /* IAR Systems compiler for embedded systems. - http://www.iar.com - Not supported yet by CMake -#elif defined(__IAR_SYSTEMS_ICC__) -# define COMPILER_ID "IAR" */ + http://www.iar.com */ +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" /* sdcc, the small devices C compiler for embedded systems, http://sdcc.sourceforge.net */ diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in index e2119c2bf..5e87715c0 100644 --- a/Modules/CMakeCXXCompilerId.cpp.in +++ b/Modules/CMakeCXXCompilerId.cpp.in @@ -161,6 +161,11 @@ #elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) # define COMPILER_ID "ADSP" +/* IAR Systems compiler for embedded systems. + http://www.iar.com */ +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + #elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) # define COMPILER_ID "MIPSpro" # if defined(_SGI_COMPILER_VERSION) diff --git a/Modules/CMakeCommonLanguageInclude.cmake b/Modules/CMakeCommonLanguageInclude.cmake index bf94f9ff6..e945aa7c8 100644 --- a/Modules/CMakeCommonLanguageInclude.cmake +++ b/Modules/CMakeCommonLanguageInclude.cmake @@ -68,6 +68,19 @@ if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) ${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO_INIT} CACHE STRING "Flags used by the linker during Release with Debug Info builds.") + set (CMAKE_STATIC_LINKER_FLAGS_DEBUG ${CMAKE_STATIC_LINKER_FLAGS_DEBUG_INIT} CACHE STRING + "Flags used by the linker during debug builds.") + + set (CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL ${CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL_INIT} + CACHE STRING + "Flags used by the linker during release minsize builds.") + + set (CMAKE_STATIC_LINKER_FLAGS_RELEASE ${CMAKE_STATIC_LINKER_FLAGS_RELEASE_INIT} CACHE STRING + "Flags used by the linker during release builds.") + + set (CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO + ${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO_INIT} CACHE STRING + "Flags used by the linker during Release with Debug Info builds.") endif() # shared linker flags set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_INIT} $ENV{LDFLAGS}" @@ -77,6 +90,10 @@ set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_INIT} $ENV{LDFLAGS}" set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS_INIT} $ENV{LDFLAGS}" CACHE STRING "Flags used by the linker during the creation of modules.") +# static linker flags +set (CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS_INIT}" + CACHE STRING "Flags used by the linker during the creation of static libraries.") + set(CMAKE_BUILD_TOOL ${CMAKE_MAKE_PROGRAM} CACHE INTERNAL "What is the target build tool cmake is generating for.") @@ -103,5 +120,10 @@ CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL CMAKE_MODULE_LINKER_FLAGS_RELEASE CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO ) diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake index 99b04e39b..0fecb5db6 100644 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@ -103,6 +103,10 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_TI "-h") set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_TI "Texas Instruments") + list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS GNU IAR) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_IAR ) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_IAR "IAR Assembler") + include(CMakeDetermineCompilerId) CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT}) diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index d2220e09e..8769c668b 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -120,6 +120,13 @@ if(NOT CMAKE_C_COMPILER_ID_RUN) set(CMAKE_C_COMPILER_ID) file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in CMAKE_C_COMPILER_ID_PLATFORM_CONTENT) + + # The IAR compiler produces weird output. + # See http://www.cmake.org/Bug/view.php?id=10176#c19598 + list(APPEND CMAKE_C_COMPILER_ID_VENDORS IAR) + set(CMAKE_C_COMPILER_ID_VENDOR_FLAGS_IAR ) + set(CMAKE_C_COMPILER_ID_VENDOR_REGEX_IAR "IAR .+ Compiler") + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) CMAKE_DETERMINE_COMPILER_ID(C CFLAGS CMakeCCompilerId.c) diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index 6f7e8f6d4..c79ba898d 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -116,6 +116,13 @@ if(NOT CMAKE_CXX_COMPILER_ID_RUN) set(CMAKE_CXX_COMPILER_ID) file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in CMAKE_CXX_COMPILER_ID_PLATFORM_CONTENT) + + # The IAR compiler produces weird output. + # See http://www.cmake.org/Bug/view.php?id=10176#c19598 + list(APPEND CMAKE_CXX_COMPILER_ID_VENDORS IAR) + set(CMAKE_CXX_COMPILER_ID_VENDOR_FLAGS_IAR ) + set(CMAKE_CXX_COMPILER_ID_VENDOR_REGEX_IAR "IAR .+ Compiler") + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) CMAKE_DETERMINE_COMPILER_ID(CXX CXXFLAGS CMakeCXXCompilerId.cpp) diff --git a/Modules/CMakeDetermineCompiler.cmake b/Modules/CMakeDetermineCompiler.cmake index 2d12c0757..f522c4408 100644 --- a/Modules/CMakeDetermineCompiler.cmake +++ b/Modules/CMakeDetermineCompiler.cmake @@ -69,4 +69,17 @@ macro(_cmake_find_compiler lang) endif() unset(_${lang}_COMPILER_HINTS) unset(_languages) + + # Look for a make tool provided by Xcode + if(CMAKE_${lang}_COMPILER STREQUAL "CMAKE_${lang}_COMPILER-NOTFOUND" AND CMAKE_HOST_APPLE) + foreach(comp ${CMAKE_${lang}_COMPILER_LIST}) + execute_process(COMMAND xcrun --find ${comp} + OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _xcrun_err) + if(_xcrun_out) + set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${_xcrun_out}") + break() + endif() + endforeach() + endif() endmacro() diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index 25d6bbea7..5d35ce378 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -38,6 +38,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) "--no-warn-unused-cli" OUTPUT_VARIABLE OUTPUT COPY_FILE "${BIN}" + COPY_FILE_ERROR _copy_error ) # Move result from cache to normal variable. set(CMAKE_${lang}_ABI_COMPILED ${CMAKE_${lang}_ABI_COMPILED}) @@ -45,7 +46,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) set(CMAKE_${lang}_ABI_COMPILED ${CMAKE_${lang}_ABI_COMPILED} PARENT_SCOPE) # Load the resulting information strings. - if(CMAKE_${lang}_ABI_COMPILED) + if(CMAKE_${lang}_ABI_COMPILED AND NOT _copy_error) message(STATUS "Detecting ${lang} compiler ABI info - done") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Detecting ${lang} compiler ABI info compiled with the following output:\n${OUTPUT}\n\n") @@ -128,7 +129,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) else() message(STATUS "Detecting ${lang} compiler ABI info - failed") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Detecting ${lang} compiler ABI info failed to compile with the following output:\n${OUTPUT}\n\n") + "Detecting ${lang} compiler ABI info failed to compile with the following output:\n${OUTPUT}\n${_copy_error}\n\n") endif() endif() endfunction() diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index b9180921d..dd0c2bdcf 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -109,12 +109,9 @@ Id flags: ${testflags} # Compile the compiler identification source. if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([0-9]+)") set(vs_version ${CMAKE_MATCH_1}) - set(id_arch ${CMAKE_VS_PLATFORM_NAME}) + set(id_platform ${CMAKE_VS_PLATFORM_NAME}) set(id_lang "${lang}") set(id_cl cl.exe) - if(NOT id_arch) - set(id_arch Win32) - endif() if(NOT "${vs_version}" VERSION_LESS 10) set(v 10) set(ext vcxproj) @@ -126,14 +123,8 @@ Id flags: ${testflags} set(v 6) set(ext dsp) endif() - if("${id_arch}" STREQUAL "x64") - set(id_machine_10 MachineX64) - elseif("${id_arch}" STREQUAL "Itanium") - set(id_machine_10 MachineIA64) - set(id_arch ia64) - else() - set(id_machine_6 x86) - set(id_machine_10 MachineX86) + if("${id_platform}" STREQUAL "Itanium") + set(id_platform ia64) endif() if(CMAKE_VS_PLATFORM_TOOLSET) set(id_toolset "<PlatformToolset>${CMAKE_VS_PLATFORM_TOOLSET}</PlatformToolset>") @@ -142,12 +133,16 @@ Id flags: ${testflags} endif() if(CMAKE_VS_WINCE_VERSION) set(id_entrypoint "mainACRTStartup") - set(id_subsystem 9) + if("${vs_version}" VERSION_LESS 9) + set(id_subsystem 9) + else() + set(id_subsystem 8) + endif() else() set(id_subsystem 1) endif() if("${CMAKE_MAKE_PROGRAM}" MATCHES "[Mm][Ss][Bb][Uu][Ii][Ll][Dd]") - set(build /p:Configuration=Debug /p:Platform=@id_arch@ /p:VisualStudioVersion=${vs_version}.0) + set(build /p:Configuration=Debug /p:Platform=@id_platform@ /p:VisualStudioVersion=${vs_version}.0) elseif("${CMAKE_MAKE_PROGRAM}" MATCHES "[Mm][Ss][Dd][Ee][Vv]") set(build /make) else() @@ -214,7 +209,7 @@ Id flags: ${testflags} # ... # /path/to/cc ...CompilerId${lang}/... # to extract the compiler front-end for the language. - if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerId${lang}/\\./CompilerId${lang}[ \t\n\\\"]") + if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerId${lang}/(\\./)?CompilerId${lang}[ \t\n\\\"]") set(_comp "${CMAKE_MATCH_2}") if(EXISTS "${_comp}") set(CMAKE_${lang}_COMPILER_ID_TOOL "${_comp}" PARENT_SCOPE) @@ -339,6 +334,35 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) endif() endforeach() + # Detect the exact architecture from the PE header. + if(WIN32) + # The offset to the PE signature is stored at 0x3c. + file(READ ${file} peoffsethex LIMIT 1 OFFSET 60 HEX) + string(SUBSTRING "${peoffsethex}" 0 1 peoffsethex1) + string(SUBSTRING "${peoffsethex}" 1 1 peoffsethex2) + set(peoffsetexpression "${peoffsethex1} * 16 + ${peoffsethex2}") + string(REPLACE "a" "10" peoffsetexpression "${peoffsetexpression}") + string(REPLACE "b" "11" peoffsetexpression "${peoffsetexpression}") + string(REPLACE "c" "12" peoffsetexpression "${peoffsetexpression}") + string(REPLACE "d" "13" peoffsetexpression "${peoffsetexpression}") + string(REPLACE "e" "14" peoffsetexpression "${peoffsetexpression}") + string(REPLACE "f" "15" peoffsetexpression "${peoffsetexpression}") + math(EXPR peoffset "${peoffsetexpression}") + + file(READ ${file} peheader LIMIT 6 OFFSET ${peoffset} HEX) + if(peheader STREQUAL "50450000a201") + set(ARCHITECTURE_ID "SH3") + elseif(peheader STREQUAL "50450000a301") + set(ARCHITECTURE_ID "SH3DSP") + elseif(peheader STREQUAL "50450000a601") + set(ARCHITECTURE_ID "SH4") + elseif(peheader STREQUAL "50450000a801") + set(ARCHITECTURE_ID "SH5") + elseif(peheader STREQUAL "50450000c201") + set(ARCHITECTURE_ID "THUMB") + endif() + endif() + # Check if a valid compiler and platform were found. if(COMPILER_ID AND NOT COMPILER_ID_TWICE) set(CMAKE_${lang}_COMPILER_ID "${COMPILER_ID}") diff --git a/Modules/CMakeDetermineRCCompiler.cmake b/Modules/CMakeDetermineRCCompiler.cmake index fa78da03c..c4600c7fe 100644 --- a/Modules/CMakeDetermineRCCompiler.cmake +++ b/Modules/CMakeDetermineRCCompiler.cmake @@ -12,14 +12,14 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -# determine the compiler to use for C programs -# NOTE, a generator may set CMAKE_C_COMPILER before +# determine the compiler to use for RC programs +# NOTE, a generator may set CMAKE_RC_COMPILER before # loading this file to force a compiler. -# use environment variable CCC first if defined by user, next use -# the cmake variable CMAKE_GENERATOR_CC which can be defined by a generator +# use environment variable RC first if defined by user, next use +# the cmake variable CMAKE_GENERATOR_RC which can be defined by a generator # as a default compiler if(NOT CMAKE_RC_COMPILER) - # prefer the environment variable CC + # prefer the environment variable RC if($ENV{RC} MATCHES ".+") get_filename_component(CMAKE_RC_COMPILER_INIT $ENV{RC} PROGRAM PROGRAM_ARGS CMAKE_RC_FLAGS_ENV_INIT) if(CMAKE_RC_FLAGS_ENV_INIT) diff --git a/Modules/CMakeDetermineVSServicePack.cmake b/Modules/CMakeDetermineVSServicePack.cmake index 98e5bb873..f49482e7f 100644 --- a/Modules/CMakeDetermineVSServicePack.cmake +++ b/Modules/CMakeDetermineVSServicePack.cmake @@ -1,32 +1,25 @@ -# - Includes a public function for assisting users in trying to determine the -# Visual Studio service pack in use. -# -# Sets the passed in variable to one of the following values or an empty -# string if unknown. -# vc80 -# vc80sp1 -# vc90 -# vc90sp1 -# vc100 -# vc100sp1 -# vc110 +# - Determine the Visual Studio service pack of the 'cl' in use. +# The functionality of this module has been superseded by the platform +# variable CMAKE_<LANG>_COMPILER_VERSION that contains the compiler version +# number. # # Usage: -# =========================== -# -# if(MSVC) -# include(CMakeDetermineVSServicePack) -# DetermineVSServicePack( my_service_pack ) -# -# if( my_service_pack ) -# message(STATUS "Detected: ${my_service_pack}") -# endif() +# if(MSVC) +# include(CMakeDetermineVSServicePack) +# DetermineVSServicePack( my_service_pack ) +# if( my_service_pack ) +# message(STATUS "Detected: ${my_service_pack}") # endif() -# -# =========================== +# endif() +# Function DetermineVSServicePack sets the given variable to one of the +# following values or an empty string if unknown: +# vc80, vc80sp1 +# vc90, vc90sp1 +# vc100, vc100sp1 +# vc110, vc110sp1, vc110sp2 #============================================================================= -# Copyright 2009-2011 Kitware, Inc. +# Copyright 2009-2013 Kitware, Inc. # Copyright 2009-2010 Philip Lowman <philip@yhbt.com> # Copyright 2010-2011 Aaron C. meadows <cmake@shadowguarddev.com> # @@ -57,6 +50,12 @@ function(_DetermineVSServicePackFromCompiler _OUT_VAR _cl_version) set(_version "vc100sp1") elseif(${_cl_version} VERSION_EQUAL "17.00.50727.1") set(_version "vc110") + elseif(${_cl_version} VERSION_EQUAL "17.00.51106.1") + set(_version "vc110sp1") + elseif(${_cl_version} VERSION_EQUAL "17.00.60315.1") + set(_version "vc110sp2") + elseif(${_cl_version} VERSION_EQUAL "17.00.60610.1") + set(_version "vc110sp3") else() set(_version "") endif() diff --git a/Modules/CMakeFindPackageMode.cmake b/Modules/CMakeFindPackageMode.cmake index cea018706..e5216f4e0 100644 --- a/Modules/CMakeFindPackageMode.cmake +++ b/Modules/CMakeFindPackageMode.cmake @@ -3,7 +3,7 @@ # NAME = name of the package # COMPILER_ID = the CMake compiler ID for which the result is, i.e. GNU/Intel/Clang/MSVC, etc. # LANGUAGE = language for which the result will be used, i.e. C/CXX/Fortan/ASM -# MODE = EXIST : only check for existance of the given package +# MODE = EXIST : only check for existence of the given package # COMPILE : print the flags needed for compiling an object file which uses the given package # LINK : print the flags needed for linking when using the given package # QUIET = if TRUE, don't print anything diff --git a/Modules/CMakeGraphVizOptions.cmake b/Modules/CMakeGraphVizOptions.cmake new file mode 100644 index 000000000..e4af54c0a --- /dev/null +++ b/Modules/CMakeGraphVizOptions.cmake @@ -0,0 +1,83 @@ +##section Variables specific to the graphviz support +##end +##module +# - The builtin graphviz support of CMake. +# CMake can generate graphviz files, showing the dependencies between +# the targets in a project and also external libraries which are linked +# against. +# When CMake is run with the --graphiz=foo option, it will produce +# * a foo.dot file showing all dependencies in the project +# * a foo.dot.<target> file for each target, file showing on which other targets the respective target depends +# * a foo.dot.<target>.dependers file, showing which other targets depend on the respective target +# +# This can result in huge graphs. Using the file CMakeGraphVizOptions.cmake +# the look and content of the generated graphs can be influenced. +# This file is searched first in ${CMAKE_BINARY_DIR} and then in +# ${CMAKE_SOURCE_DIR}. If found, it is read and the variables set in it +# are used to adjust options for the generated graphviz files. +##end +# +##variable +# GRAPHVIZ_GRAPH_TYPE - The graph type +# Mandatory : NO +# Default : "digraph" +##end +##variable +# GRAPHVIZ_GRAPH_NAME - The graph name. +# Mandatory : NO +# Default : "GG" +##end +##variable +# GRAPHVIZ_GRAPH_HEADER - The header written at the top of the graphviz file. +# Mandatory : NO +# Default : "node [n fontsize = "12"];" +##end +##variable +# GRAPHVIZ_NODE_PREFIX - The prefix for each node in the graphviz file. +# Mandatory : NO +# Default : "node" +##end +##variable +# GRAPHVIZ_EXECUTABLES - Set this to FALSE to exclude executables from the generated graphs. +# Mandatory : NO +# Default : TRUE +##end +##variable +# GRAPHVIZ_STATIC_LIBS - Set this to FALSE to exclude static libraries from the generated graphs. +# Mandatory : NO +# Default : TRUE +##end +##variable +# GRAPHVIZ_SHARED_LIBS - Set this to FALSE to exclude shared libraries from the generated graphs. +# Mandatory : NO +# Default : TRUE +##end +##variable +# GRAPHVIZ_MODULE_LIBS - Set this to FALSE to exclude static libraries from the generated graphs. +# Mandatory : NO +# Default : TRUE +##end +##variable +# GRAPHVIZ_EXTERNAL_LIBS - Set this to FALSE to exclude external libraries from the generated graphs. +# Mandatory : NO +# Default : TRUE +##end +##variable +# GRAPHVIZ_IGNORE_TARGETS - A list of regular expressions for ignoring targets. +# Mandatory : NO +# Default : empty +##end + +#============================================================================= +# Copyright 2007-2009 Kitware, Inc. +# Copyright 2013 Alexander Neundorf <neundorf@kde.org> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) diff --git a/Modules/CMakeMinGWFindMake.cmake b/Modules/CMakeMinGWFindMake.cmake index efba20a31..d7298dcef 100644 --- a/Modules/CMakeMinGWFindMake.cmake +++ b/Modules/CMakeMinGWFindMake.cmake @@ -14,7 +14,9 @@ find_program(CMAKE_MAKE_PROGRAM mingw32-make.exe PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MinGW;InstallLocation]/bin" - c:/MinGW/bin /MinGW/bin) + c:/MinGW/bin /MinGW/bin + "[HKEY_CURRENT_USER\\Software\\CodeBlocks;Path]/MinGW/bin" + ) find_program(CMAKE_SH sh.exe ) if(CMAKE_SH) message(FATAL_ERROR "sh.exe was found in your PATH, here:\n${CMAKE_SH}\nFor MinGW make to work correctly sh.exe must NOT be in your path.\nRun cmake from a shell that does not have sh.exe in your PATH.\nIf you want to use a UNIX shell, then use MSYS Makefiles.\n") diff --git a/Modules/CMakeParseArguments.cmake b/Modules/CMakeParseArguments.cmake index 406780eb4..016da0c97 100644 --- a/Modules/CMakeParseArguments.cmake +++ b/Modules/CMakeParseArguments.cmake @@ -51,7 +51,7 @@ # MY_INSTALL_CONFIGURATIONS = "" (was not used) # MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL" # -# You can the continue and process these variables. +# You can then continue and process these variables. # # Keywords terminate lists of values, e.g. if directly after a one_value_keyword # another recognized keyword follows, this is interpreted as the beginning of diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index 80e02188a..4724a8c7b 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -26,10 +26,11 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj set(linker "CMAKE_LINKER-NOTFOUND") if(CMAKE_LINKER) get_filename_component(linker ${CMAKE_LINKER} NAME) + string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" linker "${linker}") endif() # Construct a regex to match linker lines. It must match both the # whole line and just the command (argv[0]). - set(linker_regex "^( *|.*[/\\])(${linker}|ld|collect2)[^/\\]*( |$)") + set(linker_regex "^( *|.*[/\\])(${linker}|([^/\\]+-)?ld|collect2)[^/\\]*( |$)") set(linker_exclude_regex "collect2 version ") set(log "${log} link line regex: [${linker_regex}]\n") string(REGEX REPLACE "\r?\n" ";" output_lines "${text}") diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake new file mode 100644 index 000000000..ef5d857b6 --- /dev/null +++ b/Modules/CMakePrintHelpers.cmake @@ -0,0 +1,146 @@ +# - Convenience macros for printing properties and variables, useful e.g. for debugging. +# +# +# CMAKE_PRINT_PROPERTIES([TARGETS target1 .. targetN] +# [SOURCES source1 .. sourceN] +# [DIRECTORIES dir1 .. dirN] +# [TESTS test1 .. testN] +# [CACHE_ENTRIES entry1 .. entryN] +# PROPERTIES prop1 .. propN ) +# +# This macro prints the values of the properties of the given targets, +# source files, directories, tests or cache entries. Exactly one of the +# scope keywords must be used. +# Example: +# cmake_print_properties(TARGETS foo bar PROPERTIES LOCATION INTERFACE_INCLUDE_DIRS) +# This will print the LOCATION and INTERFACE_INCLUDE_DIRS properties for both +# targets foo and bar. +# +# +# CMAKE_PRINT_VARIABLES(var1 var2 .. varN) +# +# This macro will print the name of each variable followed by its value. +# Example: +# cmake_print_variables(CMAKE_C_COMPILER CMAKE_MAJOR_VERSION THIS_ONE_DOES_NOT_EXIST) +# Gives: +# -- CMAKE_C_COMPILER="/usr/bin/gcc" ; CMAKE_MAJOR_VERSION="2" ; THIS_ONE_DOES_NOT_EXIST="" + +#============================================================================= +# Copyright 2013 Alexander Neundorf, <neundorf@kde.org> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +include(CMakeParseArguments) + +function(CMAKE_PRINT_VARIABLES) + set(msg "") + foreach(var ${ARGN}) + if(msg) + set(msg "${msg} ; ") + endif() + set(msg "${msg}${var}=\"${${var}}\"") + endforeach() + message(STATUS "${msg}") +endfunction() + + +function(CMAKE_PRINT_PROPERTIES ) + set(options ) + set(oneValueArgs ) + set(multiValueArgs TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES ) + + cmake_parse_arguments(CPP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(CPP_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to cmake_print_properties(): \"${CPP_UNPARSED_ARGUMENTS}\"") + return() + endif() + + if(NOT CPP_PROPERTIES) + message(FATAL_ERROR "Required argument PROPERTIES missing in cmake_print_properties() call") + return() + endif() + + set(mode) + set(items) + set(keyword) + + if(CPP_TARGETS) + set(items ${CPP_TARGETS}) + set(mode ${mode} TARGETS) + set(keyword TARGET) + endif() + + if(CPP_SOURCES) + set(items ${CPP_SOURCES}) + set(mode ${mode} SOURCES) + set(keyword SOURCE) + endif() + + if(CPP_TESTS) + set(items ${CPP_TESTS}) + set(mode ${mode} TESTS) + set(keyword TEST) + endif() + + if(CPP_DIRECTORIES) + set(items ${CPP_DIRECTORIES}) + set(mode ${mode} DIRECTORIES) + set(keyword DIRECTORY) + endif() + + if(CPP_CACHE_ENTRIES) + set(items ${CPP_CACHE_ENTRIES}) + set(mode ${mode} CACHE_ENTRIES) + set(keyword CACHE) + endif() + + if(NOT mode) + message(FATAL_ERROR "Mode keyword missing in cmake_print_properties() call, must be one of TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES") + return() + endif() + + list(LENGTH mode modeLength) + if("${modeLength}" GREATER 1) + message(FATAL_ERROR "Multiple mode keyword used in cmake_print_properties() call, it must be exactly one of TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES") + return() + endif() + + set(msg "\n") + foreach(item ${items}) + + set(itemExists TRUE) + if(keyword STREQUAL "TARGET") + if(NOT TARGET ${item}) + set(itemExists FALSE) + set(msg "${msg}\n No such TARGET \"${item}\" !\n\n") + endif() + endif() + + if (itemExists) + set(msg "${msg} Properties for ${keyword} ${item}:\n") + foreach(prop ${CPP_PROPERTIES}) + + get_property(propertySet ${keyword} ${item} PROPERTY "${prop}" SET) + + if(propertySet) + get_property(property ${keyword} ${item} PROPERTY "${prop}") + set(msg "${msg} ${item}.${prop} = \"${property}\"\n") + else() + set(msg "${msg} ${item}.${prop} = <NOTFOUND>\n") + endif() + endforeach() + endif() + + endforeach() + message(STATUS "${msg}") + +endfunction() diff --git a/Modules/CMakePushCheckState.cmake b/Modules/CMakePushCheckState.cmake index 08809bf25..b37b706ac 100644 --- a/Modules/CMakePushCheckState.cmake +++ b/Modules/CMakePushCheckState.cmake @@ -1,8 +1,10 @@ -# This module defines two macros: +# This module defines three macros: # CMAKE_PUSH_CHECK_STATE() -# and # CMAKE_POP_CHECK_STATE() -# These two macros can be used to save and restore the state of the variables +# and +# CMAKE_RESET_CHECK_STATE() +# These macros can be used to save, restore and reset (i.e., clear contents) +# the state of the variables # CMAKE_REQUIRED_FLAGS, CMAKE_REQUIRED_DEFINITIONS, CMAKE_REQUIRED_LIBRARIES # and CMAKE_REQUIRED_INCLUDES used by the various Check-files coming with CMake, # like e.g. check_function_exists() etc. @@ -11,9 +13,16 @@ # but after the Find-module has been executed they should have the same value # as they had before. # +# CMAKE_PUSH_CHECK_STATE() macro receives optional argument RESET. Whether it's specified, +# CMAKE_PUSH_CHECK_STATE() will set all CMAKE_REQUIRED_* variables to empty values, same +# as CMAKE_RESET_CHECK_STATE() call will do. +# # Usage: -# cmake_push_check_state() -# set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -DSOME_MORE_DEF) +# cmake_push_check_state(RESET) +# set(CMAKE_REQUIRED_DEFINITIONS -DSOME_MORE_DEF) +# check_function_exists(...) +# cmake_reset_check_state() +# set(CMAKE_REQUIRED_DEFINITIONS -DANOTHER_DEF) # check_function_exists(...) # cmake_pop_check_state() @@ -31,6 +40,15 @@ # License text for the above reference.) +macro(CMAKE_RESET_CHECK_STATE) + + set(CMAKE_REQUIRED_INCLUDES) + set(CMAKE_REQUIRED_DEFINITIONS) + set(CMAKE_REQUIRED_LIBRARIES) + set(CMAKE_REQUIRED_FLAGS) + +endmacro() + macro(CMAKE_PUSH_CHECK_STATE) if(NOT DEFINED _CMAKE_PUSH_CHECK_STATE_COUNTER) @@ -43,6 +61,11 @@ macro(CMAKE_PUSH_CHECK_STATE) set(_CMAKE_REQUIRED_DEFINITIONS_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_DEFINITIONS}) set(_CMAKE_REQUIRED_LIBRARIES_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_LIBRARIES}) set(_CMAKE_REQUIRED_FLAGS_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_FLAGS}) + + if (ARGC GREATER 0 AND ARGV0 STREQUAL "RESET") + cmake_reset_check_state() + endif() + endmacro() macro(CMAKE_POP_CHECK_STATE) diff --git a/Modules/CMakeSystem.cmake.in b/Modules/CMakeSystem.cmake.in index 7e2a3584b..70c98d5ca 100644 --- a/Modules/CMakeSystem.cmake.in +++ b/Modules/CMakeSystem.cmake.in @@ -1,3 +1,8 @@ +set(CMAKE_HOST_SYSTEM "@CMAKE_HOST_SYSTEM@") +set(CMAKE_HOST_SYSTEM_NAME "@CMAKE_HOST_SYSTEM_NAME@") +set(CMAKE_HOST_SYSTEM_VERSION "@CMAKE_HOST_SYSTEM_VERSION@") +set(CMAKE_HOST_SYSTEM_PROCESSOR "@CMAKE_HOST_SYSTEM_PROCESSOR@") + @INCLUDE_CMAKE_TOOLCHAIN_FILE_IF_REQUIRED@ set(CMAKE_SYSTEM "@CMAKE_SYSTEM@") @@ -5,11 +10,6 @@ set(CMAKE_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@") set(CMAKE_SYSTEM_VERSION "@CMAKE_SYSTEM_VERSION@") set(CMAKE_SYSTEM_PROCESSOR "@CMAKE_SYSTEM_PROCESSOR@") -set(CMAKE_HOST_SYSTEM "@CMAKE_HOST_SYSTEM@") -set(CMAKE_HOST_SYSTEM_NAME "@CMAKE_HOST_SYSTEM_NAME@") -set(CMAKE_HOST_SYSTEM_VERSION "@CMAKE_HOST_SYSTEM_VERSION@") -set(CMAKE_HOST_SYSTEM_PROCESSOR "@CMAKE_HOST_SYSTEM_PROCESSOR@") - set(CMAKE_CROSSCOMPILING "@CMAKE_CROSSCOMPILING@") set(CMAKE_SYSTEM_LOADED 1) diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake index e26334514..b9e77c5f5 100644 --- a/Modules/CMakeTestFortranCompiler.cmake +++ b/Modules/CMakeTestFortranCompiler.cmake @@ -72,7 +72,7 @@ else() message(STATUS "Checking whether ${CMAKE_Fortran_COMPILER} supports Fortran 90") file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompilerF90.f90 " PROGRAM TESTFortran90 - stop = 1 ; do while ( stop .eq. 0 ) ; end do + integer stop ; stop = 1 ; do while ( stop .eq. 0 ) ; end do END PROGRAM TESTFortran90 ") try_compile(CMAKE_Fortran_COMPILER_SUPPORTS_F90 ${CMAKE_BINARY_DIR} diff --git a/Modules/CMakeUnixFindMake.cmake b/Modules/CMakeUnixFindMake.cmake index c75cf7cbc..371492657 100644 --- a/Modules/CMakeUnixFindMake.cmake +++ b/Modules/CMakeUnixFindMake.cmake @@ -14,3 +14,13 @@ find_program(CMAKE_MAKE_PROGRAM NAMES gmake make smake) mark_as_advanced(CMAKE_MAKE_PROGRAM) + +# Look for a make tool provided by Xcode +if(NOT CMAKE_MAKE_PROGRAM AND CMAKE_HOST_APPLE) + execute_process(COMMAND xcrun --find make + OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _xcrun_err) + if(_xcrun_out) + set_property(CACHE CMAKE_MAKE_PROGRAM PROPERTY VALUE "${_xcrun_out}") + endif() +endif() diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 42d3c0c39..b0260ab16 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -263,8 +263,8 @@ # ##variable # CPACK_PACKAGE_INSTALL_REGISTRY_KEY - Registry key used when -# installing this project. This is only used -# by installer for Windows. +# installing this project. This is only used by installer for Windows. +# The default value is based on the installation directory. ##end ##variable # CPACK_CREATE_DESKTOP_LINKS - List of desktop links to create. diff --git a/Modules/CPackPackageMaker.cmake b/Modules/CPackPackageMaker.cmake index 45ba465cc..98ca9e2d5 100644 --- a/Modules/CPackPackageMaker.cmake +++ b/Modules/CPackPackageMaker.cmake @@ -2,7 +2,7 @@ ##end ##module # - PackageMaker CPack generator (Mac OS X). -# The following variable is specific to installers build on Mac OS X +# The following variable is specific to installers built on Mac OS X # using PackageMaker: ##end # diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake index fa79e1bfc..bf5b5bc62 100644 --- a/Modules/CPackRPM.cmake +++ b/Modules/CPackRPM.cmake @@ -163,6 +163,8 @@ # May be set by the user in order to specify a USER binary spec file # to be used by CPackRPM instead of generating the file. # The specified file will be processed by configure_file( @ONLY). +# One can provide a component specific file by setting +# CPACK_RPM_<componentName>_USER_BINARY_SPECFILE. ##end ##variable # CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE - Spec file template. @@ -223,6 +225,24 @@ # The refered file will be read and directly put after the %changelog # section. ##end +##variable +# CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST - list of path to be excluded. +# Mandatory : NO +# Default : /etc /etc/init.d /usr /usr/share /usr/share/doc /usr/bin /usr/lib /usr/lib64 /usr/include +# May be used to exclude path (directories or files) from the auto-generated +# list of paths discovered by CPack RPM. The defaut value contains a reasonable +# set of values if the variable is not defined by the user. If the variable +# is defined by the user then CPackRPM will NOT any of the default path. +# If you want to add some path to the default list then you can use +# CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION variable. +##end +##variable +# CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION - additional list of path to be excluded. +# Mandatory : NO +# Default : - +# May be used to add more exclude path (directories or files) from the initial +# default list of excluded paths. See CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST. +##end #============================================================================= # Copyright 2007-2009 Kitware, Inc. @@ -617,7 +637,7 @@ if(CPACK_RPM_CHANGELOG_FILE) message(SEND_ERROR "CPackRPM:Warning: CPACK_RPM_CHANGELOG_FILE <${CPACK_RPM_CHANGELOG_FILE}> does not exists - ignoring") endif() else() - set(CPACK_RPM_SPEC_CHANGELOG "* Sun Jul 4 2010 Erk <eric.noulard@gmail.com>\n Generated by CPack RPM (no Changelog file were provided)") + set(CPACK_RPM_SPEC_CHANGELOG "* Sun Jul 4 2010 Eric Noulard <eric.noulard@gmail.com> - ${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}\n Generated by CPack RPM (no Changelog file were provided)") endif() # CPACK_RPM_SPEC_MORE_DEFINE @@ -666,6 +686,30 @@ if(CPACK_RPM_PACKAGE_RELOCATABLE) endforeach() endif() +if (CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: Initial list of path to OMIT in RPM: ${_RPM_DIRS_TO_OMIT}") +endif() + +if (NOT DEFINED CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST) + set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST /etc /etc/init.d /usr /usr/share /usr/share/doc /usr/bin /usr/lib /usr/lib64 /usr/include) + if (CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION) + message("CPackRPM:Debug: Adding ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION} to builtin omit list.") + list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST "${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION}") + endif() +endif() + +if(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST) + if (CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST= ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST}") + endif() + foreach(_DIR ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST}) + list(APPEND _RPM_DIRS_TO_OMIT "-o;-path;.${_DIR}") + endforeach() +endif() +if (CPACK_RPM_PACKAGE_DEBUG) + message("CPackRPM:Debug: Final list of path to OMIT in RPM: ${_RPM_DIRS_TO_OMIT}") +endif() + # Use files tree to construct files command (spec file) # We should not forget to include symlinks (thus -o -type l) # We should include directory as well (thus -type d) @@ -832,11 +876,25 @@ if(CPACK_RPM_PACKAGE_DEBUG) message("CPackRPM:Debug: CPACK_TEMPORARY_PACKAGE_FILE_NAME = ${CPACK_TEMPORARY_PACKAGE_FILE_NAME}") endif() -# USER generated spec file handling. -# We should generate a spec file template: +# protect @ in pathname in order to avoid their +# interpretation during the configure_file step +set(CPACK_RPM_INSTALL_FILES_LIST "${CPACK_RPM_INSTALL_FILES}") +set(PROTECTED_AT "@") +string(REPLACE "@" "\@PROTECTED_AT\@" CPACK_RPM_INSTALL_FILES "${CPACK_RPM_INSTALL_FILES_LIST}") +set(CPACK_RPM_INSTALL_FILES_LIST "") + +# +# USER generated/provided spec file handling. +# + +# We can have a component specific spec file. +if(CPACK_RPM_PACKAGE_COMPONENT AND CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_BINARY_SPECFILE) + set(CPACK_RPM_USER_BINARY_SPECFILE ${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_USER_BINARY_SPECFILE}) +endif() + +# We should generate a USER spec file template: # - either because the user asked for it : CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE # - or the user did not provide one : NOT CPACK_RPM_USER_BINARY_SPECFILE -# if(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE OR NOT CPACK_RPM_USER_BINARY_SPECFILE) file(WRITE ${CPACK_RPM_BINARY_SPECFILE}.in "# -*- rpm-spec -*- @@ -902,9 +960,9 @@ mv \"\@CPACK_TOPLEVEL_DIRECTORY\@/tmpBBroot\" $RPM_BUILD_ROOT %files %defattr(-,root,root,-) -${CPACK_RPM_INSTALL_FILES} -${CPACK_RPM_ABSOLUTE_INSTALL_FILES} -${CPACK_RPM_USER_INSTALL_FILES} +\@CPACK_RPM_INSTALL_FILES\@ +\@CPACK_RPM_ABSOLUTE_INSTALL_FILES\@ +\@CPACK_RPM_USER_INSTALL_FILES\@ %changelog \@CPACK_RPM_SPEC_CHANGELOG\@ @@ -931,6 +989,9 @@ else() configure_file(${CPACK_RPM_BINARY_SPECFILE}.in ${CPACK_RPM_BINARY_SPECFILE} @ONLY) endif() +# remove AT protection +unset(PROTECTED_AT) + if(RPMBUILD_EXECUTABLE) # Now call rpmbuild using the SPECFILE execute_process( diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake index 0c0a8f19f..fce25f07a 100644 --- a/Modules/CPackWIX.cmake +++ b/Modules/CPackWIX.cmake @@ -76,6 +76,32 @@ # This image must be 493 by 312 pixels. # ##end +# +##variable +# CPACK_WIX_PROGRAM_MENU_FOLDER - Start menu folder name for launcher. +# +# If this variable is not set, it will be initialized with CPACK_PACKAGE_NAME +# +##end +##variable +# CPACK_WIX_CULTURES - Language(s) of the installer +# +# Languages are compiled into the WixUI extension library. To use them, +# simply provide the name of the culture. If you specify more than one +# culture identifier in a comma or semicolon delimited list, the first one +# that is found will be used. You can find a list of supported languages at: +# http://wix.sourceforge.net/manual-wix3/WixUI_localization.htm +# +##end +##variable +# CPACK_WIX_TEMPLATE - Template file for WiX generation +# +# If this variable is set, the specified template will be used to generate the WiX wxs file. +# This should be used if further customization of the output is required. +# +# If this variable is not set, the default MSI template included with CMake will be used. +# +##end #============================================================================= # Copyright 2012 Kitware, Inc. diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake index 562e2486c..5cd62f607 100644 --- a/Modules/CTest.cmake +++ b/Modules/CTest.cmake @@ -84,13 +84,13 @@ if(BUILD_TESTING) endmacro() macro(SET_IF_SET var val) - if(NOT "${val}" MATCHES "^$") + if(NOT "${val}" STREQUAL "") set("${var}" "${val}") endif() endmacro() macro(SET_IF_SET_AND_NOT_SET var val) - if(NOT "${val}" MATCHES "^$") + if(NOT "${val}" STREQUAL "") SET_IF_NOT_SET("${var}" "${val}") endif() endmacro() diff --git a/Modules/CheckCCompilerFlag.cmake b/Modules/CheckCCompilerFlag.cmake index 08e80f756..bc15e9a0b 100644 --- a/Modules/CheckCCompilerFlag.cmake +++ b/Modules/CheckCCompilerFlag.cmake @@ -2,9 +2,13 @@ # CHECK_C_COMPILER_FLAG(<flag> <var>) # <flag> - the compiler flag # <var> - variable to store the result -# This internally calls the check_c_source_compiles macro. +# This internally calls the check_c_source_compiles macro and +# sets CMAKE_REQUIRED_DEFINITIONS to <flag>. # See help for CheckCSourceCompiles for a listing of variables -# that can modify the build. +# that can otherwise modify the build. +# The result only tells that the compiler does not give an error message when +# it encounters the flag. If the flag has any effect or even a specific one is +# beyond the scope of this module. #============================================================================= # Copyright 2006-2011 Kitware, Inc. @@ -26,6 +30,12 @@ include(CheckCSourceCompiles) macro (CHECK_C_COMPILER_FLAG _FLAG _RESULT) set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") + # Normalize locale during test compilation. + set(_CheckCCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG) + foreach(v ${_CheckCCompilerFlag_LOCALE_VARS}) + set(_CheckCCompilerFlag_SAVED_${v} "$ENV{${v}}") + set(ENV{${v}} C) + endforeach() CHECK_C_SOURCE_COMPILES("int main(void) { return 0; }" ${_RESULT} # Some compilers do not fail with a bad flag FAIL_REGEX "command line option .* is valid for .* but not for C" # GNU @@ -41,5 +51,11 @@ macro (CHECK_C_COMPILER_FLAG _FLAG _RESULT) FAIL_REGEX "command option .* is not recognized" # XL FAIL_REGEX "WARNING: unknown flag:" # Open64 ) + foreach(v ${_CheckCCompilerFlag_LOCALE_VARS}) + set(ENV{${v}} ${_CheckCCompilerFlag_SAVED_${v}}) + unset(_CheckCCompilerFlag_SAVED_${v}) + endforeach() + unset(_CheckCCompilerFlag_LOCALE_VARS) + set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") endmacro () diff --git a/Modules/CheckCXXCompilerFlag.cmake b/Modules/CheckCXXCompilerFlag.cmake index 662640340..eee3a701e 100644 --- a/Modules/CheckCXXCompilerFlag.cmake +++ b/Modules/CheckCXXCompilerFlag.cmake @@ -2,9 +2,13 @@ # CHECK_CXX_COMPILER_FLAG(<flag> <var>) # <flag> - the compiler flag # <var> - variable to store the result -# This internally calls the check_cxx_source_compiles macro. See help -# for CheckCXXSourceCompiles for a listing of variables that can -# modify the build. +# This internally calls the check_cxx_source_compiles macro and +# sets CMAKE_REQUIRED_DEFINITIONS to <flag>. +# See help for CheckCXXSourceCompiles for a listing of variables +# that can otherwise modify the build. +# The result only tells that the compiler does not give an error message when +# it encounters the flag. If the flag has any effect or even a specific one is +# beyond the scope of this module. #============================================================================= # Copyright 2006-2010 Kitware, Inc. @@ -26,6 +30,13 @@ include(CheckCXXSourceCompiles) macro (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT) set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") + + # Normalize locale during test compilation. + set(_CheckCXXCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG) + foreach(v ${_CheckCXXCompilerFlag_LOCALE_VARS}) + set(_CheckCXXCompilerFlag_SAVED_${v} "$ENV{${v}}") + set(ENV{${v}} C) + endforeach() CHECK_CXX_SOURCE_COMPILES("int main() { return 0;}" ${_RESULT} # Some compilers do not fail with a bad flag FAIL_REGEX "command line option .* is valid for .* but not for C\\\\+\\\\+" # GNU @@ -43,6 +54,12 @@ macro (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT) FAIL_REGEX "File with unknown suffix passed to linker" # PGI FAIL_REGEX "WARNING: unknown flag:" # Open64 ) + foreach(v ${_CheckCXXCompilerFlag_LOCALE_VARS}) + set(ENV{${v}} ${_CheckCXXCompilerFlag_SAVED_${v}}) + unset(_CheckCXXCompilerFlag_SAVED_${v}) + endforeach() + unset(_CheckCXXCompilerFlag_LOCALE_VARS) + set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") endmacro () diff --git a/Modules/CheckFunctionExists.cmake b/Modules/CheckFunctionExists.cmake index 7aa1748da..ead135441 100644 --- a/Modules/CheckFunctionExists.cmake +++ b/Modules/CheckFunctionExists.cmake @@ -4,7 +4,7 @@ # Check that the <function> is provided by libraries on the system and # store the result in a <variable>. This does not verify that any # system header file declares the function, only that it can be found -# at link time (considure using CheckSymbolExists). +# at link time (consider using CheckSymbolExists). # # The following variables may be set before calling this macro to # modify the way the check is run: diff --git a/Modules/CheckSizeOf.cmake b/Modules/CheckSizeOf.cmake index 9f587b5c2..f0707df4e 100644 --- a/Modules/CheckSizeOf.cmake +++ b/Modules/CheckSizeOf.cmake @@ -15,4 +15,4 @@ message(SEND_ERROR "Modules/CheckSizeOf.cmake has been removed. " "Use Modules/CheckTypeSize.cmake instead. This " - "compatability check may be removed before the next release!") + "compatibility check may be removed before the next release!") diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake index 486e2af88..972d889aa 100644 --- a/Modules/Compiler/Clang-CXX.cmake +++ b/Modules/Compiler/Clang-CXX.cmake @@ -1,2 +1,4 @@ include(Compiler/Clang) __compiler_clang(CXX) + +set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index c6cd8f8f5..ec4562a3d 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -24,4 +24,5 @@ macro(__compiler_clang lang) __compiler_gnu(${lang}) set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") + set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") endmacro() diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index 879ab8f80..33d6093a1 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -1,2 +1,12 @@ include(Compiler/GNU) __compiler_gnu(CXX) + +if (WIN32) + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) + set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fno-keep-inline-dllexport") + endif() +else() + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2) + set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") + endif() +endif() diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake index faad41672..504704dad 100644 --- a/Modules/Compiler/GNU.cmake +++ b/Modules/Compiler/GNU.cmake @@ -25,6 +25,9 @@ macro(__compiler_gnu lang) if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") endif() + if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.2) + set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") + endif() set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") diff --git a/Modules/Compiler/IAR-ASM.cmake b/Modules/Compiler/IAR-ASM.cmake new file mode 100644 index 000000000..66fb052df --- /dev/null +++ b/Modules/Compiler/IAR-ASM.cmake @@ -0,0 +1,14 @@ +# This file is processed when the IAR compiler is used for an assembler file + +include(Compiler/IAR) + +set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> <SOURCE> <DEFINES> <FLAGS> -o <OBJECT>") + +if("${IAR_TARGET_ARCHITECTURE}" STREQUAL "ARM") + set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa) +endif() + + +if("${IAR_TARGET_ARCHITECTURE}" STREQUAL "AVR") + set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s90;asm;msa) +endif() diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake new file mode 100644 index 000000000..da29447c4 --- /dev/null +++ b/Modules/Compiler/IAR-C.cmake @@ -0,0 +1,34 @@ +# This file is processed when the IAR compiler is used for a C file + + +include(Compiler/IAR) + +set(CMAKE_C_COMPILE_OBJECT "<CMAKE_C_COMPILER> <SOURCE> <DEFINES> <FLAGS> -o <OBJECT>") +set(CMAKE_C_CREATE_PREPROCESSED_SOURCE "<CMAKE_C_COMPILER> <SOURCE> <DEFINES> <FLAGS> --preprocess=cnl <PREPROCESSED_SOURCE>") +set(CMAKE_C_CREATE_ASSEMBLY_SOURCE "<CMAKE_C_COMPILER> <SOURCE> <DEFINES> <FLAGS> -lAH <ASSEMBLY_SOURCE> -o <OBJECT>.dummy") + +# The toolchains for ARM and AVR are quite different: +if("${IAR_TARGET_ARCHITECTURE}" STREQUAL "ARM") + + set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + set(CMAKE_C_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS> ") + +endif() + + +if("${IAR_TARGET_ARCHITECTURE}" STREQUAL "AVR") + set(CMAKE_C_OUTPUT_EXTENSION ".r90") + + if(NOT CMAKE_C_LINK_FLAGS) + set(CMAKE_C_LINK_FLAGS "-Fmotorola") + endif() + + set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + set(CMAKE_C_CREATE_STATIC_LIBRARY "<CMAKE_AR> -o <TARGET> <OBJECTS> ") + +endif() + +# add the target specific include directory: +get_filename_component(_compilerDir "${CMAKE_C_COMPILER}" PATH) +get_filename_component(_compilerDir "${_compilerDir}" PATH) +include_directories("${_compilerDir}/inc" ) diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake new file mode 100644 index 000000000..eae9d1b77 --- /dev/null +++ b/Modules/Compiler/IAR-CXX.cmake @@ -0,0 +1,34 @@ +# This file is processed when the IAR compiler is used for a C++ file + +include(Compiler/IAR) + +set(CMAKE_CXX_COMPILE_OBJECT "<CMAKE_CXX_COMPILER> <SOURCE> <DEFINES> <FLAGS> -o <OBJECT>") + +set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE "<CMAKE_CXX_COMPILER> <SOURCE> <DEFINES> <FLAGS> --preprocess=cnl <PREPROCESSED_SOURCE>") +set(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE "<CMAKE_CXX_COMPILER> <SOURCE> <DEFINES> <FLAGS> -lAH <ASSEMBLY_SOURCE> -o <OBJECT>.dummy") + + + +if("${IAR_TARGET_ARCHITECTURE}" STREQUAL "ARM") + + set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + set(CMAKE_CXX_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS> ") + +endif() + + +if("${IAR_TARGET_ARCHITECTURE}" STREQUAL "AVR") + set(CMAKE_CXX_OUTPUT_EXTENSION ".r90") + if(NOT CMAKE_CXX_LINK_FLAGS) + set(CMAKE_CXX_LINK_FLAGS "-Fmotorola") + endif() + + set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <OBJECTS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>") + set(CMAKE_CXX_CREATE_STATIC_LIBRARY "<CMAKE_AR> -o <TARGET> <OBJECTS> ") + +endif() + +# add the target specific include directory: +get_filename_component(_compilerDir "${CMAKE_C_COMPILER}" PATH) +get_filename_component(_compilerDir "${_compilerDir}" PATH) +include_directories("${_compilerDir}/inc") diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake new file mode 100644 index 000000000..00e47133c --- /dev/null +++ b/Modules/Compiler/IAR.cmake @@ -0,0 +1,46 @@ +# This file is processed when the IAR compiler is used for a C or C++ file +# Documentation can be downloaded here: http://www.iar.com/website1/1.0.1.0/675/1/ +# The initial feature request is here: http://www.cmake.org/Bug/view.php?id=10176 +# It also contains additional links and information. + +if(_IAR_CMAKE_LOADED) + return() +endif() +set(_IAR_CMAKE_LOADED TRUE) + + +get_filename_component(_CMAKE_C_TOOLCHAIN_LOCATION "${CMAKE_C_COMPILER}" PATH) +get_filename_component(_CMAKE_CXX_TOOLCHAIN_LOCATION "${CMAKE_CXX_COMPILER}" PATH) +get_filename_component(_CMAKE_ASM_TOOLCHAIN_LOCATION "${CMAKE_ASM_COMPILER}" PATH) + + +if("${CMAKE_C_COMPILER}" MATCHES "arm" OR "${CMAKE_CXX_COMPILER}" MATCHES "arm" OR "${CMAKE_ASM_COMPILER}" MATCHES "arm") + set(CMAKE_EXECUTABLE_SUFFIX ".elf") + + # For arm, IAR uses the "ilinkarm" linker and "iarchive" archiver: + find_program(CMAKE_IAR_LINKER ilinkarm HINTS "${_CMAKE_C_TOOLCHAIN_LOCATION}" "${_CMAKE_CXX_TOOLCHAIN_LOCATION}" "${_CMAKE_ASM_TOOLCHAIN_LOCATION}") + find_program(CMAKE_IAR_AR iarchive HINTS "${_CMAKE_C_TOOLCHAIN_LOCATION}" "${_CMAKE_CXX_TOOLCHAIN_LOCATION}" "${_CMAKE_ASM_TOOLCHAIN_LOCATION}" ) + + set(IAR_TARGET_ARCHITECTURE "ARM" CACHE STRING "IAR compiler target architecture") +endif() + +if("${CMAKE_C_COMPILER}" MATCHES "avr" OR "${CMAKE_CXX_COMPILER}" MATCHES "avr" OR "${CMAKE_ASM_COMPILER}" MATCHES "avr") + set(CMAKE_EXECUTABLE_SUFFIX ".bin") + + # For AVR and AVR32, IAR uses the "xlink" linker and the "xar" archiver: + find_program(CMAKE_IAR_LINKER xlink HINTS "${_CMAKE_C_TOOLCHAIN_LOCATION}" "${_CMAKE_CXX_TOOLCHAIN_LOCATION}" "${_CMAKE_ASM_TOOLCHAIN_LOCATION}" ) + find_program(CMAKE_IAR_AR xar HINTS "${_CMAKE_C_TOOLCHAIN_LOCATION}" "${_CMAKE_CXX_TOOLCHAIN_LOCATION}" "${_CMAKE_ASM_TOOLCHAIN_LOCATION}" ) + + set(IAR_TARGET_ARCHITECTURE "AVR" CACHE STRING "IAR compiler target architecture") + + set(CMAKE_LIBRARY_PATH_FLAG "-I") + +endif() + +if(NOT IAR_TARGET_ARCHITECTURE) + message(FATAL_ERROR "The IAR compiler for this architecture is not yet supported " + " by CMake. Please go to http://www.cmake.org/Bug and enter a feature request there.") +endif() + +set(CMAKE_LINKER "${CMAKE_IAR_LINKER}" CACHE FILEPATH "The IAR linker" FORCE) +set(CMAKE_AR "${CMAKE_IAR_AR}" CACHE FILEPATH "The IAR archiver" FORCE) diff --git a/Modules/Compiler/Intel-C.cmake b/Modules/Compiler/Intel-C.cmake index e23317c14..5b43db9f4 100644 --- a/Modules/Compiler/Intel-C.cmake +++ b/Modules/Compiler/Intel-C.cmake @@ -6,5 +6,9 @@ set(CMAKE_C_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG") set(CMAKE_C_FLAGS_RELEASE_INIT "-O3 -DNDEBUG") set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -DNDEBUG") +if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.0) + set(CMAKE_C_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") +endif() + set(CMAKE_C_CREATE_PREPROCESSED_SOURCE "<CMAKE_C_COMPILER> <DEFINES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>") set(CMAKE_C_CREATE_ASSEMBLY_SOURCE "<CMAKE_C_COMPILER> <DEFINES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>") diff --git a/Modules/Compiler/Intel-CXX.cmake b/Modules/Compiler/Intel-CXX.cmake index ae6021a68..35bb3ec04 100644 --- a/Modules/Compiler/Intel-CXX.cmake +++ b/Modules/Compiler/Intel-CXX.cmake @@ -6,5 +6,9 @@ set(CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE_INIT "-O3 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -DNDEBUG") +if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0) + set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") +endif() + set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE "<CMAKE_CXX_COMPILER> <DEFINES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>") set(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE "<CMAKE_CXX_COMPILER> <DEFINES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>") diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in index ab4705fa3..1a7a53942 100644 --- a/Modules/CompilerId/VS-10.vcxproj.in +++ b/Modules/CompilerId/VS-10.vcxproj.in @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|@id_arch@"> + <ProjectConfiguration Include="Debug|@id_platform@"> <Configuration>Debug</Configuration> - <Platform>@id_arch@</Platform> + <Platform>@id_platform@</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> @@ -12,7 +12,7 @@ <Keyword>Win32Proj</Keyword> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@id_arch@'" Label="Configuration"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> @id_toolset@ <CharacterSet>MultiByte</CharacterSet> @@ -20,11 +20,11 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <PropertyGroup> <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_arch@'">.\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_arch@'">$(Configuration)\</IntDir> - <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|@id_arch@'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">.\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">$(Configuration)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">false</LinkIncremental> </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@id_arch@'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'"> <ClCompile> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -40,7 +40,6 @@ <Link> <GenerateDebugInformation>false</GenerateDebugInformation> <SubSystem>Console</SubSystem> - <TargetMachine>@id_machine_10@</TargetMachine> </Link> <PostBuildEvent> <Command>for %%i in (@id_cl@) do %40echo CMAKE_@id_lang@_COMPILER=%%~$PATH:i</Command> diff --git a/Modules/CompilerId/VS-6.dsp.in b/Modules/CompilerId/VS-6.dsp.in index 4f7e67613..48c9a236b 100644 --- a/Modules/CompilerId/VS-6.dsp.in +++ b/Modules/CompilerId/VS-6.dsp.in @@ -1,7 +1,7 @@ # Microsoft Developer Studio Project File - Name="CompilerId@id_lang@" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 -# TARGTYPE "Win32 (@id_machine_6@) Application" 0x0101 +# TARGTYPE "Win32 (x86) Application" 0x0101 CFG=CompilerId@id_lang@ - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, @@ -16,7 +16,7 @@ CFG=CompilerId@id_lang@ - Win32 Debug !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE -!MESSAGE "CompilerId@id_lang@ - Win32 Debug" (based on "Win32 (@id_machine_6@) Application") +!MESSAGE "CompilerId@id_lang@ - Win32 Debug" (based on "Win32 (x86) Application") !MESSAGE # Begin Project @@ -29,7 +29,7 @@ CPP=cl.exe # PROP Target_Dir "" # ADD CPP /nologo /MDd /c LINK32=link.exe -# ADD LINK32 /nologo /version:0.0 /subsystem:console /machine:@id_machine_6@ /out:"CompilerId@id_lang@.exe" /IGNORE:4089 +# ADD LINK32 /nologo /version:0.0 /subsystem:console /machine:x86 /out:"CompilerId@id_lang@.exe" /IGNORE:4089 # Begin Special Build Tool SOURCE="$(InputPath)" PostBuild_Cmds=for %%i in (@id_cl@) do @echo CMAKE_@id_lang@_COMPILER=%%~$PATH:i diff --git a/Modules/CompilerId/VS-7.vcproj.in b/Modules/CompilerId/VS-7.vcproj.in index fa48cadb3..9e3c3c3ce 100644 --- a/Modules/CompilerId/VS-7.vcproj.in +++ b/Modules/CompilerId/VS-7.vcproj.in @@ -10,12 +10,12 @@ > <Platforms> <Platform - Name="@id_arch@" + Name="@id_platform@" /> </Platforms> <Configurations> <Configuration - Name="Debug|@id_arch@" + Name="Debug|@id_platform@" OutputDirectory="." IntermediateDirectory="$(ConfigurationName)" ConfigurationType="1" diff --git a/Modules/CompilerId/Xcode-1.pbxproj.in b/Modules/CompilerId/Xcode-1.pbxproj.in index f06960fec..793ad0280 100644 --- a/Modules/CompilerId/Xcode-1.pbxproj.in +++ b/Modules/CompilerId/Xcode-1.pbxproj.in @@ -56,7 +56,7 @@ 2C18F0B415DC1DC700593670 = { fileEncoding = 30; isa = PBXFileReference; - lastKnownFileType = @id_type@; + explicitFileType = @id_type@; path = @id_src@; refType = 4; sourceTree = "<group>"; diff --git a/Modules/CompilerId/Xcode-2.pbxproj.in b/Modules/CompilerId/Xcode-2.pbxproj.in index e3c7aa910..226b413fd 100644 --- a/Modules/CompilerId/Xcode-2.pbxproj.in +++ b/Modules/CompilerId/Xcode-2.pbxproj.in @@ -7,7 +7,7 @@ objects = { 2C18F0B615DC1E0300593670 = {isa = PBXBuildFile; fileRef = 2C18F0B415DC1DC700593670; }; - 2C18F0B415DC1DC700593670 = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = @id_type@; path = @id_src@; sourceTree = "<group>"; }; + 2C18F0B415DC1DC700593670 = {isa = PBXFileReference; fileEncoding = 4; explicitFileType = @id_type@; path = @id_src@; sourceTree = "<group>"; }; 8DD76F6C0486A84900D96B5E = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CompilerId@id_lang@; sourceTree = BUILT_PRODUCTS_DIR; }; 08FB7794FE84155DC02AAC07 = { diff --git a/Modules/CompilerId/Xcode-3.pbxproj.in b/Modules/CompilerId/Xcode-3.pbxproj.in index d94a803fb..6f861ebf4 100644 --- a/Modules/CompilerId/Xcode-3.pbxproj.in +++ b/Modules/CompilerId/Xcode-3.pbxproj.in @@ -7,7 +7,7 @@ objects = { 2C18F0B615DC1E0300593670 = {isa = PBXBuildFile; fileRef = 2C18F0B415DC1DC700593670; }; - 2C18F0B415DC1DC700593670 = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = @id_type@; path = @id_src@; sourceTree = "<group>"; }; + 2C18F0B415DC1DC700593670 = {isa = PBXFileReference; fileEncoding = 4; explicitFileType = @id_type@; path = @id_src@; sourceTree = "<group>"; }; 08FB7794FE84155DC02AAC07 = { isa = PBXGroup; children = ( diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index 8332725ca..50669bd29 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -391,7 +391,7 @@ function(_ExternalData_arg target arg options var_file) # Regular expression to match associated files. string(REGEX REPLACE "^REGEX:" "" regex "${opt}") list(APPEND associated_regex "${regex}") - elseif("x${opt}" MATCHES "^x:$") + elseif(opt STREQUAL ":") # Activate series matching. set(series_option "${opt}") elseif("x${opt}" MATCHES "^[^][:/*?]+$") diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 40e14d516..0781ea146 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -114,6 +114,15 @@ # and <TMP_DIR> # with corresponding property values. # +# Any builtin step that specifies a "<step>_COMMAND cmd..." or custom +# step that specifies a "COMMAND cmd..." may specify additional command +# lines using the form "COMMAND cmd...". At build time the commands will +# be executed in order and aborted if any one fails. For example: +# ... BUILD_COMMAND make COMMAND echo done ... +# specifies to run "make" and then "echo done" during the build step. +# Whether the current working directory is preserved between commands +# is not defined. Behavior of shell operators like "&&" is not defined. +# # The 'ExternalProject_Get_Property' function retrieves external project # target properties: # ExternalProject_Get_Property(<name> [prop1 [prop2 [...]]]) @@ -961,7 +970,7 @@ endif() set(sep ";") endif() endforeach() - set(code "set(ENV{VS_UNICODE_OUTPUT} \"\")\n${code}set(command \"${cmd}\")${code_execute_process}") + set(code "${code}set(command \"${cmd}\")${code_execute_process}") file(WRITE ${stamp_dir}/${name}-${step}-impl.cmake "${code}") set(command ${CMAKE_COMMAND} "-Dmake=\${make}" "-Dconfig=\${config}" -P ${stamp_dir}/${name}-${step}-impl.cmake) endif() @@ -971,7 +980,6 @@ endif() set(logbase ${stamp_dir}/${name}-${step}) file(WRITE ${script} " ${code_cygpath_make} -set(ENV{VS_UNICODE_OUTPUT} \"\") set(command \"${command}\") execute_process( COMMAND \${command} @@ -1251,10 +1259,10 @@ function(_ep_add_download_command name) get_filename_component(work_dir "${source_dir}" PATH) set(comment "Performing download step (SVN checkout) for '${name}'") set(svn_user_pw_args "") - if(svn_username) + if(DEFINED svn_username) set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}") endif() - if(svn_password) + if(DEFINED svn_password) set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}") endif() if(svn_trust_cert) @@ -1473,10 +1481,10 @@ function(_ep_add_update_command name) get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD) get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT) set(svn_user_pw_args "") - if(svn_username) + if(DEFINED svn_username) set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}") endif() - if(svn_password) + if(DEFINED svn_password) set(svn_user_pw_args ${svn_user_pw_args} "--password=${svn_password}") endif() if(svn_trust_cert) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index f2c2ce37f..914a0a5b5 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -41,7 +41,7 @@ # Boost_LIBRARY_DIR - Directory containing Boost libraries # Boost_<C>_LIBRARY_DEBUG - Component <C> library debug variant # Boost_<C>_LIBRARY_RELEASE - Component <C> library release variant -# Users may set the these hints or results as cache entries. Projects should +# Users may set these hints or results as cache entries. Projects should # not read these entries directly but instead use the above result variables. # Note that some hint names start in upper-case "BOOST". One may specify # these as environment variables if they are not specified as CMake variables @@ -154,7 +154,7 @@ #------------------------------------------------------------------------------- -# Before we go searching, check whether boost-cmake is avaialble, unless the +# Before we go searching, check whether boost-cmake is available, unless the # user specifically asked NOT to search for boost-cmake. # # If Boost_DIR is set, this behaves as any find_package call would. If not, @@ -247,7 +247,7 @@ macro(_Boost_ADJUST_LIB_VARS basename) endif() endif() - # Make variables changeble to the advanced user + # Make variables changeable to the advanced user mark_as_advanced( Boost_${basename}_LIBRARY_RELEASE Boost_${basename}_LIBRARY_DEBUG @@ -1022,7 +1022,12 @@ if(Boost_FOUND) # We were unable to find some libraries, so generate a sensible # error message that lists the libraries we were unable to find. set(Boost_ERROR_REASON - "${Boost_ERROR_REASON}\nThe following Boost libraries could not be found:\n") + "${Boost_ERROR_REASON}\nCould not find the following") + if(Boost_USE_STATIC_LIBS) + set(Boost_ERROR_REASON "${Boost_ERROR_REASON} static") + endif() + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON} Boost libraries:\n") foreach(COMPONENT ${_Boost_MISSING_COMPONENTS}) set(Boost_ERROR_REASON "${Boost_ERROR_REASON} boost_${COMPONENT}\n") diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index 423ad3d13..2705d3271 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -263,6 +263,12 @@ # Only available for CUDA version 3.2+. # CUDA_npp_LIBRARY -- NVIDIA Performance Primitives library. # Only available for CUDA version 4.0+. +# CUDA_nppc_LIBRARY -- NVIDIA Performance Primitives library (core). +# Only available for CUDA version 5.5+. +# CUDA_nppi_LIBRARY -- NVIDIA Performance Primitives library (image processing). +# Only available for CUDA version 5.5+. +# CUDA_npps_LIBRARY -- NVIDIA Performance Primitives library (signal processing). +# Only available for CUDA version 5.5+. # CUDA_nvcuvenc_LIBRARY -- CUDA Video Encoder library. # Only available for CUDA version 3.2+. # Windows only. @@ -496,6 +502,9 @@ if(NOT "${CUDA_TOOLKIT_ROOT_DIR}" STREQUAL "${CUDA_TOOLKIT_ROOT_DIR_INTERNAL}") unset(CUDA_curand_LIBRARY CACHE) unset(CUDA_cusparse_LIBRARY CACHE) unset(CUDA_npp_LIBRARY CACHE) + unset(CUDA_nppc_LIBRARY CACHE) + unset(CUDA_nppi_LIBRARY CACHE) + unset(CUDA_npps_LIBRARY CACHE) unset(CUDA_nvcuvenc_LIBRARY CACHE) unset(CUDA_nvcuvid_LIBRARY CACHE) endif() @@ -607,7 +616,11 @@ macro(cuda_find_library_local_first_with_path_ext _var _names _doc _path_ext ) NO_DEFAULT_PATH ) # Search default search paths, after we search our own set of paths. - find_library(${_var} NAMES ${_names} DOC ${_doc}) + find_library(${_var} + NAMES ${_names} + PATHS "/usr/lib/nvidia-current" + DOC ${_doc} + ) endmacro() macro(cuda_find_library_local_first _var _names _doc) @@ -696,7 +709,13 @@ if(NOT CUDA_VERSION VERSION_LESS "3.2") find_cuda_helper_libs(nvcuvid) endif() endif() -if(NOT CUDA_VERSION VERSION_LESS "4.0") +if(CUDA_VERSION VERSION_GREATER "5.0") + # In CUDA 5.5 NPP was splitted onto 3 separate libraries. + find_cuda_helper_libs(nppc) + find_cuda_helper_libs(nppi) + find_cuda_helper_libs(npps) + set(CUDA_npp_LIBRARY "${CUDA_nppc_LIBRARY};${CUDA_nppi_LIBRARY};${CUDA_npps_LIBRARY}") +elseif(NOT CUDA_VERSION VERSION_LESS "4.0") find_cuda_helper_libs(npp) endif() @@ -920,7 +939,13 @@ function(CUDA_COMPUTE_BUILD_PATH path build_path) if (IS_ABSOLUTE "${bpath}") # Absolute paths are generally unnessary, especially if something like # file(GLOB_RECURSE) is used to pick up the files. - file(RELATIVE_PATH bpath "${CMAKE_CURRENT_SOURCE_DIR}" "${bpath}") + + string(FIND "${bpath}" "${CMAKE_CURRENT_BINARY_DIR}" _binary_dir_pos) + if (_binary_dir_pos EQUAL 0) + file(RELATIVE_PATH bpath "${CMAKE_CURRENT_BINARY_DIR}" "${bpath}") + else() + file(RELATIVE_PATH bpath "${CMAKE_CURRENT_SOURCE_DIR}" "${bpath}") + endif() endif() # This recipie is from cmLocalGenerator::CreateSafeUniqueObjectFileName in the @@ -1021,7 +1046,10 @@ macro(CUDA_WRAP_SRCS cuda_target format generated_files) # Initialize our list of includes with the user ones followed by the CUDA system ones. set(CUDA_NVCC_INCLUDE_ARGS ${CUDA_NVCC_INCLUDE_ARGS_USER} "-I${CUDA_INCLUDE_DIRS}") # Get the include directories for this directory and use them for our nvcc command. + # Remove duplicate entries which may be present since include_directories + # in CMake >= 2.8.8 does not remove them. get_directory_property(CUDA_NVCC_INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES) + list(REMOVE_DUPLICATES CUDA_NVCC_INCLUDE_DIRECTORIES) if(CUDA_NVCC_INCLUDE_DIRECTORIES) foreach(dir ${CUDA_NVCC_INCLUDE_DIRECTORIES}) list(APPEND CUDA_NVCC_INCLUDE_ARGS -I${dir}) @@ -1279,22 +1307,7 @@ macro(CUDA_WRAP_SRCS cuda_target format generated_files) # Make sure the build system knows the file is generated. set_source_files_properties(${generated_file} PROPERTIES GENERATED TRUE) - # Don't add the object file to the list of generated files if we are using - # visual studio and we are attaching the build rule to the cuda file. VS - # will add our object file to the linker automatically for us. - set(cuda_add_generated_file TRUE) - - if(NOT compile_to_ptx AND CMAKE_GENERATOR MATCHES "Visual Studio" AND CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE) - # Visual Studio 8 crashes when you close the solution when you don't add the object file. - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio 8") - #message("Not adding ${generated_file}") - set(cuda_add_generated_file FALSE) - endif() - endif() - - if(cuda_add_generated_file) - list(APPEND _cuda_wrap_generated_files ${generated_file}) - endif() + list(APPEND _cuda_wrap_generated_files ${generated_file}) # Add the other files that we want cmake to clean on a cleanup ########## list(APPEND CUDA_ADDITIONAL_CLEAN_FILES "${cmake_dependency_file}") diff --git a/Modules/FindCUDA/make2cmake.cmake b/Modules/FindCUDA/make2cmake.cmake index c2405f44f..1b53d177d 100644 --- a/Modules/FindCUDA/make2cmake.cmake +++ b/Modules/FindCUDA/make2cmake.cmake @@ -63,7 +63,7 @@ if (${depend_text} MATCHES ".+") if (EXISTS "/${file}") set(file "/${file}") else() - message(WARNING " Removing non-existant dependency file: ${file}") + message(WARNING " Removing non-existent dependency file: ${file}") set(file "") endif() endif() diff --git a/Modules/FindFLTK2.cmake b/Modules/FindFLTK2.cmake index 071c318ff..09f6925cc 100644 --- a/Modules/FindFLTK2.cmake +++ b/Modules/FindFLTK2.cmake @@ -45,7 +45,7 @@ if(APPLE) set( FLTK2_PLATFORM_DEPENDENT_LIBS "-framework Carbon -framework Cocoa -framework ApplicationServices -lz") endif() -# If FLTK2_INCLUDE_DIR is already defined we assigne its value to FLTK2_DIR +# If FLTK2_INCLUDE_DIR is already defined we assign its value to FLTK2_DIR if(FLTK2_INCLUDE_DIR) set(FLTK2_DIR ${FLTK2_INCLUDE_DIR}) else() diff --git a/Modules/FindFreetype.cmake b/Modules/FindFreetype.cmake index 1df239904..ccea99165 100644 --- a/Modules/FindFreetype.cmake +++ b/Modules/FindFreetype.cmake @@ -50,6 +50,9 @@ find_path(FREETYPE_INCLUDE_DIR_ft2build ft2build.h /usr/local/X11R6 /usr/local/X11 /usr/freeware + ENV GTKMM_BASEPATH + [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path] PATH_SUFFIXES include/freetype2 include ) @@ -61,6 +64,9 @@ find_path(FREETYPE_INCLUDE_DIR_freetype2 freetype/config/ftheader.h /usr/local/X11R6 /usr/local/X11 /usr/freeware + ENV GTKMM_BASEPATH + [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path] PATH_SUFFIXES include/freetype2 include ) @@ -70,10 +76,13 @@ find_library(FREETYPE_LIBRARY ENV FREETYPE_DIR PATH_SUFFIXES lib PATHS - /usr/X11R6 - /usr/local/X11R6 - /usr/local/X11 - /usr/freeware + /usr/X11R6 + /usr/local/X11R6 + /usr/local/X11 + /usr/freeware + ENV GTKMM_BASEPATH + [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path] ) # set the user variables diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake index 06cf96244..77aac6dae 100644 --- a/Modules/FindGTK2.cmake +++ b/Modules/FindGTK2.cmake @@ -18,6 +18,7 @@ # GTK2_FOUND - Were all of your specified components found? # GTK2_INCLUDE_DIRS - All include directories # GTK2_LIBRARIES - All libraries +# GTK2_DEFINITIONS - Additional compiler flags # # GTK2_VERSION - The version of GTK2 found (x.y.z) # GTK2_MAJOR_VERSION - The major version of GTK2 @@ -27,7 +28,6 @@ # Optional variables you can define prior to calling this module: # # GTK2_DEBUG - Enables verbose debugging of the module -# GTK2_SKIP_MARK_AS_ADVANCED - Disable marking cache variables as advanced # GTK2_ADDITIONAL_SUFFIXES - Allows defining additional directories to # search for include files # @@ -66,6 +66,18 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) +# Version 1.5 (UNRELEASED) (CMake 2.8.12) +# * 14236: Detect gthread library +# Detect pangocairo on windows +# Detect pangocairo with gtk module instead of with gtkmm +# * 14259: Use vc100 libraries with MSVC11 +# * 14260: Export a GTK2_DEFINITIONS variable to set /vd2 when appropriate +# (i.e. MSVC) +# * Use the optimized/debug syntax for _LIBRARY and _LIBRARIES variables when +# appropriate. A new set of _RELEASE variables was also added. +# * Remove GTK2_SKIP_MARK_AS_ADVANCED option, as now the variables are +# marked as advanced by SelectLibraryConfigurations +# * Detect gmodule, pangoft2 and pangoxft libraries # Version 1.4 (10/4/2012) (CMake 2.8.10) # * 12596: Missing paths for FindGTK2 on NetBSD # * 12049: Fixed detection of GTK include files in the lib folder on @@ -116,6 +128,9 @@ # _OUT_micro = Micro version number # _gtkversion_hdr = Header file to parse #============================================================= + +include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) + function(_GTK2_GET_VERSION _OUT_major _OUT_minor _OUT_micro _gtkversion_hdr) file(STRINGS ${_gtkversion_hdr} _contents REGEX "#define GTK_M[A-Z]+_VERSION[ \t]+") if(_contents) @@ -144,7 +159,7 @@ endfunction() #============================================================= # _GTK2_FIND_INCLUDE_DIR # Internal function to find the GTK include directories -# _var = variable to set +# _var = variable to set (_INCLUDE_DIR is appended) # _hdr = header file to look for #============================================================= function(_GTK2_FIND_INCLUDE_DIR _var _hdr) @@ -199,7 +214,7 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr) message(STATUS "Adding ${_gtk2_arch_dir} to search path for multiarch support") endif() endif() - find_path(${_var} ${_hdr} + find_path(${_var}_INCLUDE_DIR ${_hdr} PATHS ${_gtk2_arch_dir} /usr/local/lib64 @@ -226,11 +241,8 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr) ${_suffixes} ) - if(${_var}) - set(GTK2_INCLUDE_DIRS ${GTK2_INCLUDE_DIRS} ${${_var}} PARENT_SCOPE) - if(NOT GTK2_SKIP_MARK_AS_ADVANCED) - mark_as_advanced(${_var}) - endif() + if(${_var}_INCLUDE_DIR) + set(GTK2_INCLUDE_DIRS ${GTK2_INCLUDE_DIRS} ${${_var}_INCLUDE_DIR} PARENT_SCOPE) endif() endfunction() @@ -238,7 +250,7 @@ endfunction() #============================================================= # _GTK2_FIND_LIBRARY # Internal function to find libraries packaged with GTK2 -# _var = library variable to create +# _var = library variable to create (_LIBRARY is appended) #============================================================= function(_GTK2_FIND_LIBRARY _var _lib _expand_vc _append_version) @@ -268,6 +280,9 @@ function(_GTK2_FIND_LIBRARY _var _lib _expand_vc _append_version) set(_library ${_library}-vc90) elseif(MSVC10) set(_library ${_library}-vc100) + elseif(MSVC11) + # Up to gtkmm-win 2.22.0-2 there are no vc110 libraries but vc100 can be used + set(_library ${_library}-vc100) endif() set(_library_d ${_library}-d) endif() @@ -317,10 +332,10 @@ function(_GTK2_FIND_LIBRARY _var _lib _expand_vc _append_version) if(GTK2_DEBUG) message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] " - "While searching for ${_var}, our proposed library list is ${_lib_list}") + "While searching for ${_var}_LIBRARY, our proposed library list is ${_lib_list}") endif() - find_library(${_var} + find_library(${_var}_LIBRARY_RELEASE NAMES ${_lib_list} PATHS /opt/gnome/lib @@ -334,34 +349,34 @@ function(_GTK2_FIND_LIBRARY _var _lib _expand_vc _append_version) if(_expand_vc AND MSVC) if(GTK2_DEBUG) message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] " - "While searching for ${_var}_DEBUG our proposed library list is ${_libd_list}") + "While searching for ${_var}_LIBRARY_DEBUG our proposed library list is ${_libd_list}") endif() - find_library(${_var}_DEBUG + find_library(${_var}_LIBRARY_DEBUG NAMES ${_libd_list} PATHS $ENV{GTKMM_BASEPATH}/lib [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path]/lib [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path]/lib ) + endif() - if(${_var} AND ${_var}_DEBUG) - if(NOT GTK2_SKIP_MARK_AS_ADVANCED) - mark_as_advanced(${_var}_DEBUG) - endif() - set(GTK2_LIBRARIES ${GTK2_LIBRARIES} optimized ${${_var}} debug ${${_var}_DEBUG}) - set(GTK2_LIBRARIES ${GTK2_LIBRARIES} PARENT_SCOPE) - endif() - else() - if(NOT GTK2_SKIP_MARK_AS_ADVANCED) - mark_as_advanced(${_var}) - endif() - set(GTK2_LIBRARIES ${GTK2_LIBRARIES} ${${_var}}) - set(GTK2_LIBRARIES ${GTK2_LIBRARIES} PARENT_SCOPE) - # Set debug to release - set(${_var}_DEBUG ${${_var}}) - set(${_var}_DEBUG ${${_var}} PARENT_SCOPE) + select_library_configurations(${_var}) + + set(${_var}_LIBRARY ${${_var}_LIBRARY} PARENT_SCOPE) + + set(GTK2_LIBRARIES ${GTK2_LIBRARIES} ${${_var}_LIBRARY}) + set(GTK2_LIBRARIES ${GTK2_LIBRARIES} PARENT_SCOPE) + + if(GTK2_DEBUG) + message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] " + "${_var}_LIBRARY_RELEASE = \"${${_var}_LIBRARY_RELEASE}\"") + message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] " + "${_var}_LIBRARY_DEBUG = \"${${_var}_LIBRARY_DEBUG}\"") + message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] " + "${_var}_LIBRARY = \"${${_var}_LIBRARY}\"") endif() + endfunction() #============================================================= @@ -373,6 +388,7 @@ endfunction() set(GTK2_FOUND) set(GTK2_INCLUDE_DIRS) set(GTK2_LIBRARIES) +set(GTK2_DEFINITIONS) if(NOT GTK2_FIND_COMPONENTS) # Assume they only want GTK @@ -389,7 +405,7 @@ if(GTK2_FIND_VERSION) message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] " "Searching for version ${GTK2_FIND_VERSION}") endif() - _GTK2_FIND_INCLUDE_DIR(GTK2_GTK_INCLUDE_DIR gtk/gtk.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_GTK gtk/gtk.h) if(GTK2_GTK_INCLUDE_DIR) _GTK2_GET_VERSION(GTK2_MAJOR_VERSION GTK2_MINOR_VERSION @@ -439,88 +455,95 @@ list(APPEND GTK2_LIBRARIES ${FREETYPE_LIBRARIES}) foreach(_GTK2_component ${GTK2_FIND_COMPONENTS}) if(_GTK2_component STREQUAL "gtk") - _GTK2_FIND_INCLUDE_DIR(GTK2_GTK_INCLUDE_DIR gtk/gtk.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_GTK gtk/gtk.h) if(UNIX) - _GTK2_FIND_LIBRARY (GTK2_GTK_LIBRARY gtk-x11 false true) - _GTK2_FIND_LIBRARY (GTK2_GDK_LIBRARY gdk-x11 false true) + _GTK2_FIND_LIBRARY (GTK2_GTK gtk-x11 false true) + _GTK2_FIND_LIBRARY (GTK2_GDK gdk-x11 false true) else() - _GTK2_FIND_LIBRARY (GTK2_GTK_LIBRARY gtk-win32 false true) - _GTK2_FIND_LIBRARY (GTK2_GDK_LIBRARY gdk-win32 false true) + _GTK2_FIND_LIBRARY (GTK2_GTK gtk-win32 false true) + _GTK2_FIND_LIBRARY (GTK2_GDK gdk-win32 false true) endif() - _GTK2_FIND_INCLUDE_DIR(GTK2_GDK_INCLUDE_DIR gdk/gdk.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_GDKCONFIG_INCLUDE_DIR gdkconfig.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_GDK gdk/gdk.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_GDKCONFIG gdkconfig.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_CAIRO_INCLUDE_DIR cairo.h) - _GTK2_FIND_LIBRARY (GTK2_CAIRO_LIBRARY cairo false false) + _GTK2_FIND_INCLUDE_DIR(GTK2_CAIRO cairo.h) + _GTK2_FIND_LIBRARY (GTK2_CAIRO cairo false false) - _GTK2_FIND_INCLUDE_DIR(GTK2_FONTCONFIG_INCLUDE_DIR fontconfig/fontconfig.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_FONTCONFIG fontconfig/fontconfig.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_PANGO_INCLUDE_DIR pango/pango.h) - _GTK2_FIND_LIBRARY (GTK2_PANGO_LIBRARY pango false true) + _GTK2_FIND_INCLUDE_DIR(GTK2_PANGO pango/pango.h) + _GTK2_FIND_LIBRARY (GTK2_PANGO pango false true) - _GTK2_FIND_INCLUDE_DIR(GTK2_GDK_PIXBUF_INCLUDE_DIR gdk-pixbuf/gdk-pixbuf.h) - _GTK2_FIND_LIBRARY (GTK2_GDK_PIXBUF_LIBRARY gdk_pixbuf false true) + _GTK2_FIND_LIBRARY (GTK2_PANGOCAIRO pangocairo false true) - _GTK2_FIND_LIBRARY (GTK2_GIO_LIBRARY gio false true) + _GTK2_FIND_LIBRARY (GTK2_PANGOFT2 pangoft2 false true) - _GTK2_FIND_INCLUDE_DIR(GTK2_ATK_INCLUDE_DIR atk/atk.h) - _GTK2_FIND_LIBRARY (GTK2_ATK_LIBRARY atk false true) + _GTK2_FIND_LIBRARY (GTK2_PANGOXFT pangoxft false true) - _GTK2_FIND_INCLUDE_DIR(GTK2_GOBJECT_INCLUDE_DIR gobject/gobject.h) - _GTK2_FIND_LIBRARY (GTK2_GOBJECT_LIBRARY gobject false true) + _GTK2_FIND_INCLUDE_DIR(GTK2_GDK_PIXBUF gdk-pixbuf/gdk-pixbuf.h) + _GTK2_FIND_LIBRARY (GTK2_GDK_PIXBUF gdk_pixbuf false true) - _GTK2_FIND_INCLUDE_DIR(GTK2_GLIB_INCLUDE_DIR glib.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBCONFIG_INCLUDE_DIR glibconfig.h) - _GTK2_FIND_LIBRARY (GTK2_GLIB_LIBRARY glib false true) + _GTK2_FIND_LIBRARY (GTK2_GTHREAD gthread false true) - elseif(_GTK2_component STREQUAL "gtkmm") + _GTK2_FIND_LIBRARY (GTK2_GMODULE gmodule false true) + + _GTK2_FIND_LIBRARY (GTK2_GIO gio false true) + + _GTK2_FIND_INCLUDE_DIR(GTK2_ATK atk/atk.h) + _GTK2_FIND_LIBRARY (GTK2_ATK atk false true) + + _GTK2_FIND_INCLUDE_DIR(GTK2_GOBJECT gobject/gobject.h) + _GTK2_FIND_LIBRARY (GTK2_GOBJECT gobject false true) - _GTK2_FIND_INCLUDE_DIR(GTK2_GTKMM_INCLUDE_DIR gtkmm.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_GTKMMCONFIG_INCLUDE_DIR gtkmmconfig.h) - _GTK2_FIND_LIBRARY (GTK2_GTKMM_LIBRARY gtkmm true true) + _GTK2_FIND_INCLUDE_DIR(GTK2_GLIB glib.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBCONFIG glibconfig.h) + _GTK2_FIND_LIBRARY (GTK2_GLIB glib false true) - _GTK2_FIND_INCLUDE_DIR(GTK2_GDKMM_INCLUDE_DIR gdkmm.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_GDKMMCONFIG_INCLUDE_DIR gdkmmconfig.h) - _GTK2_FIND_LIBRARY (GTK2_GDKMM_LIBRARY gdkmm true true) + elseif(_GTK2_component STREQUAL "gtkmm") - _GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMM_INCLUDE_DIR pangomm.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMMCONFIG_INCLUDE_DIR pangommconfig.h) - _GTK2_FIND_LIBRARY (GTK2_PANGOMM_LIBRARY pangomm true true) + _GTK2_FIND_INCLUDE_DIR(GTK2_GTKMM gtkmm.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_GTKMMCONFIG gtkmmconfig.h) + _GTK2_FIND_LIBRARY (GTK2_GTKMM gtkmm true true) - _GTK2_FIND_LIBRARY (GTK2_PANGOCAIRO_LIBRARY pangocairo true true) + _GTK2_FIND_INCLUDE_DIR(GTK2_GDKMM gdkmm.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_GDKMMCONFIG gdkmmconfig.h) + _GTK2_FIND_LIBRARY (GTK2_GDKMM gdkmm true true) - _GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMM_INCLUDE_DIR cairomm/cairomm.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMMCONFIG_INCLUDE_DIR cairommconfig.h) - _GTK2_FIND_LIBRARY (GTK2_CAIROMM_LIBRARY cairomm true true) + _GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMM pangomm.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMMCONFIG pangommconfig.h) + _GTK2_FIND_LIBRARY (GTK2_PANGOMM pangomm true true) - _GTK2_FIND_INCLUDE_DIR(GTK2_GIOMM_INCLUDE_DIR giomm.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_GIOMMCONFIG_INCLUDE_DIR giommconfig.h) - _GTK2_FIND_LIBRARY (GTK2_GIOMM_LIBRARY giomm true true) + _GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMM cairomm/cairomm.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMMCONFIG cairommconfig.h) + _GTK2_FIND_LIBRARY (GTK2_CAIROMM cairomm true true) - _GTK2_FIND_INCLUDE_DIR(GTK2_ATKMM_INCLUDE_DIR atkmm.h) - _GTK2_FIND_LIBRARY (GTK2_ATKMM_LIBRARY atkmm true true) + _GTK2_FIND_INCLUDE_DIR(GTK2_GIOMM giomm.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_GIOMMCONFIG giommconfig.h) + _GTK2_FIND_LIBRARY (GTK2_GIOMM giomm true true) - _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMM_INCLUDE_DIR glibmm.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMMCONFIG_INCLUDE_DIR glibmmconfig.h) - _GTK2_FIND_LIBRARY (GTK2_GLIBMM_LIBRARY glibmm true true) + _GTK2_FIND_INCLUDE_DIR(GTK2_ATKMM atkmm.h) + _GTK2_FIND_LIBRARY (GTK2_ATKMM atkmm true true) - _GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++_INCLUDE_DIR sigc++/sigc++.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++CONFIG_INCLUDE_DIR sigc++config.h) - _GTK2_FIND_LIBRARY (GTK2_SIGC++_LIBRARY sigc true true) + _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMM glibmm.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMMCONFIG glibmmconfig.h) + _GTK2_FIND_LIBRARY (GTK2_GLIBMM glibmm true true) + _GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++ sigc++/sigc++.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++CONFIG sigc++config.h) + _GTK2_FIND_LIBRARY (GTK2_SIGC++ sigc true true) elseif(_GTK2_component STREQUAL "glade") - _GTK2_FIND_INCLUDE_DIR(GTK2_GLADE_INCLUDE_DIR glade/glade.h) - _GTK2_FIND_LIBRARY (GTK2_GLADE_LIBRARY glade false true) + _GTK2_FIND_INCLUDE_DIR(GTK2_GLADE glade/glade.h) + _GTK2_FIND_LIBRARY (GTK2_GLADE glade false true) elseif(_GTK2_component STREQUAL "glademm") - _GTK2_FIND_INCLUDE_DIR(GTK2_GLADEMM_INCLUDE_DIR libglademm.h) - _GTK2_FIND_INCLUDE_DIR(GTK2_GLADEMMCONFIG_INCLUDE_DIR libglademmconfig.h) - _GTK2_FIND_LIBRARY (GTK2_GLADEMM_LIBRARY glademm true true) + _GTK2_FIND_INCLUDE_DIR(GTK2_GLADEMM libglademm.h) + _GTK2_FIND_INCLUDE_DIR(GTK2_GLADEMMCONFIG libglademmconfig.h) + _GTK2_FIND_LIBRARY (GTK2_GLADEMM glademm true true) else() message(FATAL_ERROR "Unknown GTK2 component ${_component}") @@ -539,6 +562,20 @@ if(NOT GTK2_FIND_VERSION AND GTK2_GTK_INCLUDE_DIR) endif() # +# On MSVC, according to https://wiki.gnome.org/gtkmm/MSWindows, the /vd2 flag needs to be +# passed to the compiler in order to use gtkmm +# +if(MSVC) + foreach(_GTK2_component ${GTK2_FIND_COMPONENTS}) + if(_GTK2_component STREQUAL "gtkmm") + set(GTK2_DEFINITIONS "/vd2") + elseif(_GTK2_component STREQUAL "glademm") + set(GTK2_DEFINITIONS "/vd2") + endif() + endforeach() +endif() + +# # Try to enforce components # @@ -606,6 +643,7 @@ else() set(GTK2_VERSION_PATCH) set(GTK2_INCLUDE_DIRS) set(GTK2_LIBRARIES) + set(GTK2_DEFINITIONS) endif() if(GTK2_INCLUDE_DIRS) diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 851416439..0c246a1df 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -289,27 +289,13 @@ if( NOT HDF5_FOUND ) ENV HDF5_ROOT PATH_SUFFIXES lib Lib ) select_library_configurations( HDF5_${LIB} ) - # even though we adjusted the individual library names in - # select_library_configurations, we still need to distinguish - # between debug and release variants because HDF5_LIBRARIES will - # need to specify different lists for debug and optimized builds. - # We can't just use the HDF5_${LIB}_LIBRARY variable (which was set - # up by the selection macro above) because it may specify debug and - # optimized variants for a particular library, but a list of - # libraries is allowed to specify debug and optimized only once. - list( APPEND HDF5_${LANGUAGE}_LIBRARIES_DEBUG - ${HDF5_${LIB}_LIBRARY_DEBUG} ) - list( APPEND HDF5_${LANGUAGE}_LIBRARIES_RELEASE - ${HDF5_${LIB}_LIBRARY_RELEASE} ) + list(APPEND HDF5_${LANGUAGE}_LIBRARIES ${HDF5_${LIB}_LIBRARY}) endforeach() list( APPEND HDF5_LIBRARY_DIRS ${HDF5_${LANGUAGE}_LIBRARY_DIRS} ) # Append the libraries for this language binding to the list of all # required libraries. - list( APPEND HDF5_LIBRARIES_DEBUG - ${HDF5_${LANGUAGE}_LIBRARIES_DEBUG} ) - list( APPEND HDF5_LIBRARIES_RELEASE - ${HDF5_${LANGUAGE}_LIBRARIES_RELEASE} ) + list(APPEND HDF5_LIBRARIES ${HDF5_${LANGUAGE}_LIBRARIES}) endforeach() # We may have picked up some duplicates in various lists during the above @@ -329,30 +315,10 @@ if( NOT HDF5_FOUND ) if( HDF5_INCLUDE_DIRS ) _remove_duplicates_from_beginning( HDF5_INCLUDE_DIRS ) endif() - if( HDF5_LIBRARIES_DEBUG ) - _remove_duplicates_from_beginning( HDF5_LIBRARIES_DEBUG ) - endif() - if( HDF5_LIBRARIES_RELEASE ) - _remove_duplicates_from_beginning( HDF5_LIBRARIES_RELEASE ) - endif() if( HDF5_LIBRARY_DIRS ) _remove_duplicates_from_beginning( HDF5_LIBRARY_DIRS ) endif() - # Construct the complete list of HDF5 libraries with debug and optimized - # variants when the generator supports them. - if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) - set( HDF5_LIBRARIES ) - foreach( _lib ${HDF5_LIBRARIES_DEBUG} ) - list( APPEND HDF5_LIBRARIES debug ${_lib} ) - endforeach() - foreach( _lib ${HDF5_LIBRARIES_RELEASE} ) - list( APPEND HDF5_LIBRARIES optimized ${_lib} ) - endforeach() - else() - set( HDF5_LIBRARIES ${HDF5_LIBRARIES_RELEASE} ) - endif() - # If the HDF5 include directory was found, open H5pubconf.h to determine if # HDF5 was compiled with parallel IO support set( HDF5_IS_PARALLEL FALSE ) diff --git a/Modules/FindITK.cmake b/Modules/FindITK.cmake index b0b3f03f0..2929a764c 100644 --- a/Modules/FindITK.cmake +++ b/Modules/FindITK.cmake @@ -17,7 +17,7 @@ # # USE_ITK_FILE - The full path to the UseITK.cmake file. # This is provided for backward -# compatability. Use ITK_USE_FILE +# compatibility. Use ITK_USE_FILE # instead. #============================================================================= @@ -52,6 +52,6 @@ if(NOT ITK_FOUND) endif() if(ITK_FOUND) - # Set USE_ITK_FILE for backward-compatability. + # Set USE_ITK_FILE for backward-compatibility. set(USE_ITK_FILE ${ITK_USE_FILE}) endif() diff --git a/Modules/FindImageMagick.cmake b/Modules/FindImageMagick.cmake index cd97b3845..7c6cce786 100644 --- a/Modules/FindImageMagick.cmake +++ b/Modules/FindImageMagick.cmake @@ -81,7 +81,7 @@ function(FIND_IMAGEMAGICK_API component header) ${ImageMagick_INCLUDE_DIRS} "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/include" PATH_SUFFIXES - ImageMagick + ImageMagick ImageMagick-6 DOC "Path to the ImageMagick include dir." ) find_library(ImageMagick_${component}_LIBRARY @@ -147,17 +147,17 @@ foreach(component ${ImageMagick_FIND_COMPONENTS} ) if(component STREQUAL "Magick++") FIND_IMAGEMAGICK_API(Magick++ Magick++.h - Magick++ CORE_RL_Magick++_ Magick++-6.Q16 Magick++-Q16 Magick++-6.Q8 Magick++-Q8 + Magick++ CORE_RL_Magick++_ Magick++-6.Q16 Magick++-Q16 Magick++-6.Q8 Magick++-Q8 Magick++-6.Q16HDRI Magick++-Q16HDRI Magick++-6.Q8HDRI Magick++-Q8HDRI ) list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_Magick++_LIBRARY) elseif(component STREQUAL "MagickWand") FIND_IMAGEMAGICK_API(MagickWand wand/MagickWand.h - Wand MagickWand CORE_RL_wand_ MagickWand-6.Q16 MagickWand-Q16 MagickWand-6.Q8 MagickWand-Q8 + Wand MagickWand CORE_RL_wand_ MagickWand-6.Q16 MagickWand-Q16 MagickWand-6.Q8 MagickWand-Q8 MagickWand-6.Q16HDRI MagickWand-Q16HDRI MagickWand-6.Q8HDRI MagickWand-Q8HDRI ) list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickWand_LIBRARY) elseif(component STREQUAL "MagickCore") FIND_IMAGEMAGICK_API(MagickCore magick/MagickCore.h - Magick MagickCore CORE_RL_magick_ MagickCore-6.Q16 MagickCore-Q16 MagickCore-6.Q8 MagickCore-Q8 + Magick MagickCore CORE_RL_magick_ MagickCore-6.Q16 MagickCore-Q16 MagickCore-6.Q8 MagickCore-Q8 MagickCore-6.Q16HDRI MagickCore-Q16HDRI MagickCore-6.Q8HDRI MagickCore-Q8HDRI ) list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickCore_LIBRARY) else() diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 143d10af0..0eb86a80a 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -86,7 +86,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/GetPrerequisites.cmake) # # The compilers are detected in this order: # -# 1. Try to find the most generic availble MPI compiler, as this is usually set up by +# 1. Try to find the most generic available MPI compiler, as this is usually set up by # cluster admins. e.g., if plain old mpicc is available, we'll use it and assume it's # the right compiler. # diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake index 96c4d8db5..83fcc3dc7 100644 --- a/Modules/FindOpenGL.cmake +++ b/Modules/FindOpenGL.cmake @@ -28,111 +28,107 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -if (WIN32) - if (CYGWIN) +set(_OpenGL_REQUIRED_VARS OPENGL_gl_LIBRARY) - find_path(OPENGL_INCLUDE_DIR GL/gl.h ) +if (CYGWIN) - find_library(OPENGL_gl_LIBRARY opengl32 ) + find_path(OPENGL_INCLUDE_DIR GL/gl.h ) + list(APPEND _OpenGL_REQUIRED_VARS OPENGL_INCLUDE_DIR) - find_library(OPENGL_glu_LIBRARY glu32 ) + find_library(OPENGL_gl_LIBRARY opengl32 ) - else () + find_library(OPENGL_glu_LIBRARY glu32 ) - if(BORLAND) - set (OPENGL_gl_LIBRARY import32 CACHE STRING "OpenGL library for win32") - set (OPENGL_glu_LIBRARY import32 CACHE STRING "GLU library for win32") - else() - set (OPENGL_gl_LIBRARY opengl32 CACHE STRING "OpenGL library for win32") - set (OPENGL_glu_LIBRARY glu32 CACHE STRING "GLU library for win32") - endif() - - endif () +elseif (WIN32) -else () + if(BORLAND) + set (OPENGL_gl_LIBRARY import32 CACHE STRING "OpenGL library for win32") + set (OPENGL_glu_LIBRARY import32 CACHE STRING "GLU library for win32") + else() + set (OPENGL_gl_LIBRARY opengl32 CACHE STRING "OpenGL library for win32") + set (OPENGL_glu_LIBRARY glu32 CACHE STRING "GLU library for win32") + endif() - if (APPLE) +elseif (APPLE) - find_library(OPENGL_gl_LIBRARY OpenGL DOC "OpenGL lib for OSX") - find_library(OPENGL_glu_LIBRARY AGL DOC "AGL lib for OSX") - find_path(OPENGL_INCLUDE_DIR OpenGL/gl.h DOC "Include for OpenGL on OSX") + find_library(OPENGL_gl_LIBRARY OpenGL DOC "OpenGL lib for OSX") + find_library(OPENGL_glu_LIBRARY AGL DOC "AGL lib for OSX") + find_path(OPENGL_INCLUDE_DIR OpenGL/gl.h DOC "Include for OpenGL on OSX") + list(APPEND _OpenGL_REQUIRED_VARS OPENGL_INCLUDE_DIR) - else() - if (CMAKE_SYSTEM_NAME MATCHES "HP-UX") - # Handle HP-UX cases where we only want to find OpenGL in either hpux64 - # or hpux32 depending on if we're doing a 64 bit build. - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(_OPENGL_LIB_PATH - /opt/graphics/OpenGL/lib/hpux32/) - else() - set(_OPENGL_LIB_PATH - /opt/graphics/OpenGL/lib/hpux64/ - /opt/graphics/OpenGL/lib/pa20_64) - endif() - elseif(CMAKE_SYSTEM_NAME STREQUAL Haiku) +else() + if (CMAKE_SYSTEM_NAME MATCHES "HP-UX") + # Handle HP-UX cases where we only want to find OpenGL in either hpux64 + # or hpux32 depending on if we're doing a 64 bit build. + if(CMAKE_SIZEOF_VOID_P EQUAL 4) set(_OPENGL_LIB_PATH - /boot/develop/lib/x86) - set(_OPENGL_INCLUDE_PATH - /boot/develop/headers/os/opengl) + /opt/graphics/OpenGL/lib/hpux32/) + else() + set(_OPENGL_LIB_PATH + /opt/graphics/OpenGL/lib/hpux64/ + /opt/graphics/OpenGL/lib/pa20_64) endif() + elseif(CMAKE_SYSTEM_NAME STREQUAL Haiku) + set(_OPENGL_LIB_PATH + /boot/develop/lib/x86) + set(_OPENGL_INCLUDE_PATH + /boot/develop/headers/os/opengl) + endif() - # The first line below is to make sure that the proper headers - # are used on a Linux machine with the NVidia drivers installed. - # They replace Mesa with NVidia's own library but normally do not - # install headers and that causes the linking to - # fail since the compiler finds the Mesa headers but NVidia's library. - # Make sure the NVIDIA directory comes BEFORE the others. - # - Atanas Georgiev <atanas@cs.columbia.edu> - - find_path(OPENGL_INCLUDE_DIR GL/gl.h - /usr/share/doc/NVIDIA_GLX-1.0/include - /usr/openwin/share/include - /opt/graphics/OpenGL/include /usr/X11R6/include - ${_OPENGL_INCLUDE_PATH} - ) - - find_path(OPENGL_xmesa_INCLUDE_DIR GL/xmesa.h - /usr/share/doc/NVIDIA_GLX-1.0/include - /usr/openwin/share/include - /opt/graphics/OpenGL/include /usr/X11R6/include - ) - - find_library(OPENGL_gl_LIBRARY - NAMES GL MesaGL - PATHS /opt/graphics/OpenGL/lib - /usr/openwin/lib - /usr/shlib /usr/X11R6/lib - ${_OPENGL_LIB_PATH} - ) - - unset(_OPENGL_INCLUDE_PATH) - unset(_OPENGL_LIB_PATH) - - # On Unix OpenGL most certainly always requires X11. - # Feel free to tighten up these conditions if you don't - # think this is always true. - # It's not true on OSX. - - if (OPENGL_gl_LIBRARY) - if(NOT X11_FOUND) - include(${CMAKE_CURRENT_LIST_DIR}/FindX11.cmake) - endif() - if (X11_FOUND) - if (NOT APPLE) - set (OPENGL_LIBRARIES ${X11_LIBRARIES}) - endif () - endif () + # The first line below is to make sure that the proper headers + # are used on a Linux machine with the NVidia drivers installed. + # They replace Mesa with NVidia's own library but normally do not + # install headers and that causes the linking to + # fail since the compiler finds the Mesa headers but NVidia's library. + # Make sure the NVIDIA directory comes BEFORE the others. + # - Atanas Georgiev <atanas@cs.columbia.edu> + + find_path(OPENGL_INCLUDE_DIR GL/gl.h + /usr/share/doc/NVIDIA_GLX-1.0/include + /usr/openwin/share/include + /opt/graphics/OpenGL/include /usr/X11R6/include + ${_OPENGL_INCLUDE_PATH} + ) + list(APPEND _OpenGL_REQUIRED_VARS OPENGL_INCLUDE_DIR) + + find_path(OPENGL_xmesa_INCLUDE_DIR GL/xmesa.h + /usr/share/doc/NVIDIA_GLX-1.0/include + /usr/openwin/share/include + /opt/graphics/OpenGL/include /usr/X11R6/include + ) + + find_library(OPENGL_gl_LIBRARY + NAMES GL MesaGL + PATHS /opt/graphics/OpenGL/lib + /usr/openwin/lib + /usr/shlib /usr/X11R6/lib + ${_OPENGL_LIB_PATH} + ) + + unset(_OPENGL_INCLUDE_PATH) + unset(_OPENGL_LIB_PATH) + + # On Unix OpenGL most certainly always requires X11. + # Feel free to tighten up these conditions if you don't + # think this is always true. + + if (OPENGL_gl_LIBRARY) + if(NOT X11_FOUND) + include(${CMAKE_CURRENT_LIST_DIR}/FindX11.cmake) + endif() + if (X11_FOUND) + set (OPENGL_LIBRARIES ${X11_LIBRARIES}) endif () + endif () - find_library(OPENGL_glu_LIBRARY - NAMES GLU MesaGLU - PATHS ${OPENGL_gl_LIBRARY} - /opt/graphics/OpenGL/lib - /usr/openwin/lib - /usr/shlib /usr/X11R6/lib - ) + find_library(OPENGL_glu_LIBRARY + NAMES GLU MesaGLU + PATHS ${OPENGL_gl_LIBRARY} + /opt/graphics/OpenGL/lib + /usr/openwin/lib + /usr/shlib /usr/X11R6/lib + ) - endif() endif () if(OPENGL_gl_LIBRARY) @@ -162,7 +158,8 @@ set(OPENGL_INCLUDE_PATH ${OPENGL_INCLUDE_DIR}) # handle the QUIETLY and REQUIRED arguments and set OPENGL_FOUND to TRUE if # all listed variables are TRUE include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGL DEFAULT_MSG OPENGL_gl_LIBRARY) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGL REQUIRED_VARS ${_OpenGL_REQUIRED_VARS}) +unset(_OpenGL_REQUIRED_VARS) mark_as_advanced( OPENGL_INCLUDE_DIR diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index f4a9f44c6..8afad6822 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -31,6 +31,8 @@ set(_OPENMP_REQUIRED_VARS) function(_OPENMP_FLAG_CANDIDATES LANG) set(OpenMP_FLAG_CANDIDATES + #Empty, if compiler automatically accepts openmp + " " #GNU "-fopenmp" #Microsoft Visual Studio @@ -39,8 +41,6 @@ function(_OPENMP_FLAG_CANDIDATES LANG) "-Qopenmp" #PathScale, Intel "-openmp" - #Empty, if compiler automatically accepts openmp - " " #Sun "-xopenmp" #HP @@ -64,6 +64,7 @@ function(_OPENMP_FLAG_CANDIDATES LANG) set(OMP_FLAG_PGI "-mp") set(OMP_FLAG_SunPro "-xopenmp") set(OMP_FLAG_XL "-qsmp") + set(OMP_FLAG_Cray " ") # Move the flag that matches the compiler to the head of the list, # this is faster and doesn't clutter the output that much. If that @@ -100,7 +101,7 @@ if(CMAKE_C_COMPILER_LOADED) include(${CMAKE_CURRENT_LIST_DIR}/CheckCSourceCompiles.cmake) endif() - foreach(FLAG ${OpenMP_C_FLAG_CANDIDATES}) + foreach(FLAG IN LISTS OpenMP_C_FLAG_CANDIDATES) set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") set(CMAKE_REQUIRED_FLAGS "${FLAG}") unset(OpenMP_FLAG_DETECTED CACHE) @@ -134,7 +135,7 @@ if(CMAKE_CXX_COMPILER_LOADED) set(OpenMP_CXX_TEST_SOURCE ${OpenMP_C_TEST_SOURCE}) endif() - foreach(FLAG ${OpenMP_CXX_FLAG_CANDIDATES}) + foreach(FLAG IN LISTS OpenMP_CXX_FLAG_CANDIDATES) set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") set(CMAKE_REQUIRED_FLAGS "${FLAG}") unset(OpenMP_FLAG_DETECTED CACHE) diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake index 224c88e0e..9851f67ad 100644 --- a/Modules/FindOpenSSL.cmake +++ b/Modules/FindOpenSSL.cmake @@ -140,10 +140,10 @@ if(WIN32 AND NOT CYGWIN) set( OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY} ) elseif(MINGW) - # same player, for MingW + # same player, for MinGW set(LIB_EAY_NAMES libeay32) set(SSL_EAY_NAMES ssleay32) - if(CMAKE_CROSS_COMPILING) + if(CMAKE_CROSSCOMPILING) list(APPEND LIB_EAY_NAMES crypto) list(APPEND SSL_EAY_NAMES ssl) endif() diff --git a/Modules/FindPNG.cmake b/Modules/FindPNG.cmake index d96d2ccf9..a2577d26b 100644 --- a/Modules/FindPNG.cmake +++ b/Modules/FindPNG.cmake @@ -38,8 +38,42 @@ if(ZLIB_FOUND) /usr/local/include/libpng # OpenBSD ) - set(PNG_NAMES ${PNG_NAMES} png libpng png15 libpng15 png15d libpng15d png14 libpng14 png14d libpng14d png12 libpng12 png12d libpng12d) - find_library(PNG_LIBRARY NAMES ${PNG_NAMES} ) + list(APPEND PNG_NAMES png libpng) + unset(PNG_NAMES_DEBUG) + set(_PNG_VERSION_SUFFIXES 17 16 15 14 12) + if (PNG_FIND_VERSION MATCHES "^[0-9]+\\.[0-9]+(\\..*)?$") + string(REGEX REPLACE + "^([0-9]+)\\.([0-9]+).*" "\\1\\2" + _PNG_VERSION_SUFFIX_MIN "${PNG_FIND_VERSION}") + if (PNG_FIND_VERSION_EXACT) + set(_PNG_VERSION_SUFFIXES ${_PNG_VERSION_SUFFIX_MIN}) + else () + string(REGEX REPLACE + "${_PNG_VERSION_SUFFIX_MIN}.*" "${_PNG_VERSION_SUFFIX_MIN}" + _PNG_VERSION_SUFFIXES "${_PNG_VERSION_SUFFIXES}") + endif () + unset(_PNG_VERSION_SUFFIX_MIN) + endif () + foreach(v IN LISTS _PNG_VERSION_SUFFIXES) + list(APPEND PNG_NAMES png${v} libpng${v}) + list(APPEND PNG_NAMES_DEBUG png${v}d libpng${v}d) + endforeach() + unset(_PNG_VERSION_SUFFIXES) + # For compatiblity with versions prior to this multi-config search, honor + # any PNG_LIBRARY that is already specified and skip the search. + if(NOT PNG_LIBRARY) + find_library(PNG_LIBRARY_RELEASE NAMES ${PNG_NAMES}) + find_library(PNG_LIBRARY_DEBUG NAMES ${PNG_NAMES_DEBUG}) + include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) + select_library_configurations(PNG) + mark_as_advanced(PNG_LIBRARY_RELEASE PNG_LIBRARY_DEBUG) + endif() + unset(PNG_NAMES) + unset(PNG_NAMES_DEBUG) + + # Set by select_library_configurations(), but we want the one from + # find_package_handle_standard_args() below. + unset(PNG_FOUND) if (PNG_LIBRARY AND PNG_PNG_INCLUDE_DIR) # png.h includes zlib.h. Sigh. diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake index af0c2ddf0..2972198b3 100644 --- a/Modules/FindProtobuf.cmake +++ b/Modules/FindProtobuf.cmake @@ -156,6 +156,16 @@ function(_protobuf_find_libraries name filename) endif() endfunction() +# Internal function: find threads library +function(_protobuf_find_threads) + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) + find_package(Threads) + if(Threads_FOUND) + list(APPEND PROTOBUF_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) + set(PROTOBUF_LIBRARIES "${PROTOBUF_LIBRARIES}" PARENT_SCOPE) + endif() +endfunction() + # # Main. # @@ -190,6 +200,9 @@ if(MSVC) set(CMAKE_FIND_LIBRARY_PREFIXES "${PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES}") endif() +if(UNIX) + _protobuf_find_threads() +endif() # Find the include directory find_path(PROTOBUF_INCLUDE_DIR diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake index 4c05cc03f..1d17ba3ae 100644 --- a/Modules/FindQt4.cmake +++ b/Modules/FindQt4.cmake @@ -100,6 +100,7 @@ # because you need a custom filename for the moc file or something similar. # # macro QT4_AUTOMOC(sourcefile1 sourcefile2 ... ) +# The qt4_automoc macro is obsolete. Use the CMAKE_AUTOMOC feature instead. # This macro is still experimental. # It can be used to have moc automatically handled. # So if you have the files foo.h and foo.cpp, and in foo.h a @@ -115,7 +116,7 @@ # You should have a look on the AUTOMOC property for targets to achieve the same results. # # macro QT4_ADD_DBUS_INTERFACE(outfiles interface basename) -# Create a the interface header and implementation files with the +# Create the interface header and implementation files with the # given basename from the given interface xml file and add it to # the list of sources. # @@ -171,9 +172,10 @@ # in: ts_files # generates commands to create .qm from .ts - files. The generated # filenames can be found in qm_files. The ts_files -# must exists and are not updated in any way. +# must exist and are not updated in any way. # # function QT4_USE_MODULES( target [link_type] modules...) +# This function is obsolete. Use target_link_libraries with IMPORTED targets instead. # Make <target> use the <modules> from Qt. Using a Qt module means # to link to the library, add the relevant include directories for the module, # and add the relevant compiler defines for using the module. @@ -495,7 +497,7 @@ macro (_QT4_ADJUST_LIB_VARS _camelCaseBasename) set(QT_INCLUDES "${QT_${basename}_INCLUDE_DIR}" ${QT_INCLUDES}) endif () - # Make variables changeble to the advanced user + # Make variables changeable to the advanced user mark_as_advanced(QT_${basename}_LIBRARY QT_${basename}_LIBRARY_RELEASE QT_${basename}_LIBRARY_DEBUG QT_${basename}_INCLUDE_DIR) endmacro () @@ -635,10 +637,10 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) ) endif() - # try dropping a hint if trying to use Visual Studio with Qt built by mingw + # try dropping a hint if trying to use Visual Studio with Qt built by MinGW if(NOT QT_QTCORE_LIBRARY_RELEASE AND MSVC) if(EXISTS ${QT_LIBRARY_DIR_TMP}/libqtmain.a) - message( FATAL_ERROR "It appears you're trying to use Visual Studio with Qt built by mingw. Those compilers do not produce code compatible with each other.") + message( FATAL_ERROR "It appears you're trying to use Visual Studio with Qt built by MinGW. Those compilers do not produce code compatible with each other.") endif() endif() @@ -657,8 +659,11 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) message(WARNING "${QT_QMAKE_EXECUTABLE} reported QT_INSTALL_LIBS as \"${QT_LIBRARY_DIR_TMP}\" " "but QtCore could not be found there. " "Qt is NOT installed correctly for the target build environment.") + set(Qt4_FOUND FALSE) if(Qt4_FIND_REQUIRED) message( FATAL_ERROR "Could NOT find QtCore. Check ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log for more details.") + else() + return() endif() endif() @@ -771,7 +776,7 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) endif() endif () - # Make variables changeble to the advanced user + # Make variables changeable to the advanced user mark_as_advanced( QT_LIBRARY_DIR QT_DOC_DIR QT_MKSPECS_DIR QT_PLUGINS_DIR QT_TRANSLATIONS_DIR) @@ -881,20 +886,16 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) endforeach() if(Q_WS_WIN) - if (QT_QAXCONTAINER_FOUND) - set(QT_MODULES ${QT_MODULES} QAxContainer) - # Set QT_AXCONTAINER_INCLUDE_DIR and QT_AXSERVER_INCLUDE_DIR - find_path(QT_QAXCONTAINER_INCLUDE_DIR ActiveQt - PATHS ${QT_HEADERS_DIR}/ActiveQt - NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH - ) - endif() - if (QT_QAXSERVER_FOUND) - find_path(QT_QAXSERVER_INCLUDE_DIR ActiveQt - PATHS ${QT_HEADERS_DIR}/ActiveQt - NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH - ) - endif() + set(QT_MODULES ${QT_MODULES} QAxContainer QAxServer) + # Set QT_AXCONTAINER_INCLUDE_DIR and QT_AXSERVER_INCLUDE_DIR + find_path(QT_QAXCONTAINER_INCLUDE_DIR ActiveQt + PATHS ${QT_HEADERS_DIR}/ActiveQt + NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH + ) + find_path(QT_QAXSERVER_INCLUDE_DIR ActiveQt + PATHS ${QT_HEADERS_DIR}/ActiveQt + NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH + ) endif() # Set QT_QTDESIGNERCOMPONENTS_INCLUDE_DIR @@ -1011,6 +1012,7 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) macro(_qt4_add_target_depends _QT_MODULE) get_target_property(_configs Qt4::${_QT_MODULE} IMPORTED_CONFIGURATIONS) + _qt4_add_target_depends_internal(${_QT_MODULE} INTERFACE_LINK_LIBRARIES ${ARGN}) foreach(_config ${_configs}) _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_INTERFACE_LIBRARIES_${_config} ${ARGN}) endforeach() @@ -1055,8 +1057,8 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) if(Q_WS_WIN) _QT4_ADJUST_LIB_VARS(qtmain) + _QT4_ADJUST_LIB_VARS(QAxServer) if(QT_QAXSERVER_FOUND) - _QT4_ADJUST_LIB_VARS(QAxServer) set_property(TARGET Qt4::QAxServer PROPERTY INTERFACE_QT4_NO_LINK_QTMAIN ON ) @@ -1064,9 +1066,7 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) COMPATIBLE_INTERFACE_BOOL QT4_NO_LINK_QTMAIN) endif() - if(QT_QAXCONTAINER_FOUND) - _QT4_ADJUST_LIB_VARS(QAxContainer) - endif() + _QT4_ADJUST_LIB_VARS(QAxContainer) endif() # Only public dependencies are listed here. @@ -1117,6 +1117,10 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) set(_isNotExcluded $<NOT:$<BOOL:$<TARGET_PROPERTY:QT4_NO_LINK_QTMAIN>>>) set(_isPolicyNEW $<TARGET_POLICY:CMP0020>) get_target_property(_configs Qt4::QtCore IMPORTED_CONFIGURATIONS) + set_property(TARGET Qt4::QtCore APPEND PROPERTY + INTERFACE_LINK_LIBRARIES + $<$<AND:${_isExe},${_isWin32},${_isNotExcluded},${_isPolicyNEW}>:Qt4::qtmain> + ) foreach(_config ${_configs}) set_property(TARGET Qt4::QtCore APPEND PROPERTY IMPORTED_LINK_INTERFACE_LIBRARIES_${_config} diff --git a/Modules/FindTCL.cmake b/Modules/FindTCL.cmake index f649ddc56..37e43d05a 100644 --- a/Modules/FindTCL.cmake +++ b/Modules/FindTCL.cmake @@ -172,6 +172,8 @@ set(TCLTK_POSSIBLE_INCLUDE_PATHS /usr/include/tcl8.3 /usr/include/tcl8.2 /usr/include/tcl8.0 + /usr/local/include/tcl8.6 + /usr/local/include/tk8.6 /usr/local/include/tcl8.5 /usr/local/include/tk8.5 /usr/local/include/tcl8.4 diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake index 5d7677791..f03908ea0 100644 --- a/Modules/FindThreads.cmake +++ b/Modules/FindThreads.cmake @@ -93,7 +93,7 @@ else() COMPILE_OUTPUT_VARIABLE OUTPUT) if(THREADS_HAVE_PTHREAD_ARG) - if(THREADS_PTHREAD_ARG MATCHES "^2$") + if(THREADS_PTHREAD_ARG STREQUAL "2") set(Threads_FOUND TRUE) message(STATUS "Check if compiler accepts -pthread - yes") else() diff --git a/Modules/FindVTK.cmake b/Modules/FindVTK.cmake index 0dede2d8b..085d60d04 100644 --- a/Modules/FindVTK.cmake +++ b/Modules/FindVTK.cmake @@ -51,7 +51,7 @@ if("${VTK_FIND_VERSION}" VERSION_LESS 4.1) endif() endif() -# Construct consitent error messages for use below. +# Construct consistent error messages for use below. set(VTK_DIR_DESCRIPTION "directory containing VTKConfig.cmake. This is either the root of the build tree, or PREFIX/lib/vtk for an installation.") if(_VTK_40_ALLOW) set(VTK_DIR_DESCRIPTION "${VTK_DIR_DESCRIPTION} For VTK 4.0, this is the location of UseVTK.cmake. This is either the root of the build tree or PREFIX/include/vtk for an installation.") @@ -127,7 +127,7 @@ endif() #----------------------------------------------------------------------------- if(VTK_FOUND) - # Set USE_VTK_FILE for backward-compatability. + # Set USE_VTK_FILE for backward-compatibility. set(USE_VTK_FILE ${VTK_USE_FILE}) else() # VTK not found, explain to the user how to specify its location. diff --git a/Modules/FindX11.cmake b/Modules/FindX11.cmake index 3cd3cefeb..131d97994 100644 --- a/Modules/FindX11.cmake +++ b/Modules/FindX11.cmake @@ -68,6 +68,7 @@ if (UNIX) /usr/openwin/include /usr/openwin/share/include /opt/graphics/OpenGL/include + /opt/X11/include ) set(X11_LIB_SEARCH_PATH @@ -75,6 +76,7 @@ if (UNIX) /usr/X11R6/lib /usr/X11R7/lib /usr/openwin/lib + /opt/X11/lib ) find_path(X11_X11_INCLUDE_PATH X11/X.h ${X11_INC_SEARCH_PATH}) diff --git a/Modules/FindXMLRPC.cmake b/Modules/FindXMLRPC.cmake index 6bb578b46..c80249b56 100644 --- a/Modules/FindXMLRPC.cmake +++ b/Modules/FindXMLRPC.cmake @@ -53,7 +53,7 @@ if(XMLRPC_FOUND) endif() # Parse the include flags. - if("${XMLRPC_C_CONFIG_RESULT}" MATCHES "^0$") + if("${XMLRPC_C_CONFIG_RESULT}" STREQUAL "0") # Convert the compile flags to a CMake list. string(REGEX REPLACE " +" ";" XMLRPC_C_CONFIG_CFLAGS "${XMLRPC_C_CONFIG_CFLAGS}") @@ -91,7 +91,7 @@ if(XMLRPC_FOUND) endif() # Parse the library names and directories. - if("${XMLRPC_C_CONFIG_RESULT}" MATCHES "^0$") + if("${XMLRPC_C_CONFIG_RESULT}" STREQUAL "0") string(REGEX REPLACE " +" ";" XMLRPC_C_CONFIG_LIBS "${XMLRPC_C_CONFIG_LIBS}") diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake index 218d47613..37a894c4d 100644 --- a/Modules/FindwxWidgets.cmake +++ b/Modules/FindwxWidgets.cmake @@ -458,7 +458,7 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32") wxWidgets-2.5.2 wxWidgets-2.5.1 wxWidgets - DOC "wxWidgets base/installation directory?" + DOC "wxWidgets base/installation directory" ) # If wxWidgets_ROOT_DIR changed, clear lib dir. @@ -492,7 +492,7 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32") PATHS ${WX_ROOT_DIR}/lib/${WX_LIB_DIR_PREFIX}_dll # prefer shared ${WX_ROOT_DIR}/lib/${WX_LIB_DIR_PREFIX}_lib - DOC "Path to wxWidgets libraries?" + DOC "Path to wxWidgets libraries" NO_DEFAULT_PATH ) else() @@ -509,7 +509,7 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32") PATHS ${WX_ROOT_DIR}/lib/${WX_LIB_DIR_PREFIX}_lib # prefer static ${WX_ROOT_DIR}/lib/${WX_LIB_DIR_PREFIX}_dll - DOC "Path to wxWidgets libraries?" + DOC "Path to wxWidgets libraries" NO_DEFAULT_PATH ) endif() @@ -703,6 +703,7 @@ else() #----------------------------------------------------------------- # Support cross-compiling, only search in the target platform. find_program(wxWidgets_CONFIG_EXECUTABLE wx-config + DOC "Location of wxWidgets library configuration provider binary (wx-config)." ONLY_CMAKE_FIND_ROOT_PATH ) @@ -843,6 +844,7 @@ set(wxWidgets_FOUND ${WXWIDGETS_FOUND}) # Resource file compiler. find_program(wxWidgets_wxrc_EXECUTABLE wxrc ${wxWidgets_ROOT_DIR}/utils/wxrc/vc_msw + DOC "Location of wxWidgets resource file compiler binary (wxrc)" ) # diff --git a/Modules/FindwxWindows.cmake b/Modules/FindwxWindows.cmake index 4179f7bb2..868d20c73 100644 --- a/Modules/FindwxWindows.cmake +++ b/Modules/FindwxWindows.cmake @@ -321,7 +321,7 @@ if(WIN32_STYLE_FIND) rpcrt4 wsock32 ) - ## HACK: feed in to optimized / debug libaries if both were FOUND. + ## HACK: feed in to optimized / debug libraries if both were FOUND. set(WXWINDOWS_STATIC_DEBUG_LIBS ${WXWINDOWS_STATIC_DEBUG_LIBS} wxbase26d wxbase26d_net @@ -354,7 +354,7 @@ if(WIN32_STYLE_FIND) ## ## if there is at least one shared lib available - ## let user choose wether to use shared or static wxwindows libs + ## let user choose whether to use shared or static wxwindows libs if(WXWINDOWS_SHARED_LIBRARY OR WXWINDOWS_SHARED_DEBUG_LIBRARY) ## default value OFF because wxWindows MSVS default build is static option(WXWINDOWS_USE_SHARED_LIBS @@ -606,7 +606,7 @@ else() ../wx/bin ../../wx/bin ) - # check wether wx-config was found: + # check whether wx-config was found: if(CMAKE_WXWINDOWS_WXCONFIG_EXECUTABLE) # use shared/static wx lib? diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake index 892ebc6dd..4ef14ac28 100644 --- a/Modules/GenerateExportHeader.cmake +++ b/Modules/GenerateExportHeader.cmake @@ -267,6 +267,7 @@ macro(_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) if(_GEH_EXPORT_MACRO_NAME) set(EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_EXPORT_MACRO_NAME}) endif() + string(MAKE_C_IDENTIFIER ${EXPORT_MACRO_NAME} EXPORT_MACRO_NAME) if(_GEH_EXPORT_FILE_NAME) if(IS_ABSOLUTE ${_GEH_EXPORT_FILE_NAME}) set(EXPORT_FILE_NAME ${_GEH_EXPORT_FILE_NAME}) @@ -277,12 +278,15 @@ macro(_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) if(_GEH_DEPRECATED_MACRO_NAME) set(DEPRECATED_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_DEPRECATED_MACRO_NAME}) endif() + string(MAKE_C_IDENTIFIER ${DEPRECATED_MACRO_NAME} DEPRECATED_MACRO_NAME) if(_GEH_NO_EXPORT_MACRO_NAME) set(NO_EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_NO_EXPORT_MACRO_NAME}) endif() + string(MAKE_C_IDENTIFIER ${NO_EXPORT_MACRO_NAME} NO_EXPORT_MACRO_NAME) if(_GEH_STATIC_DEFINE) set(STATIC_DEFINE ${_GEH_PREFIX_NAME}${_GEH_STATIC_DEFINE}) endif() + string(MAKE_C_IDENTIFIER ${STATIC_DEFINE} STATIC_DEFINE) if(_GEH_DEFINE_NO_DEPRECATED) set(DEFINE_NO_DEPRECATED TRUE) @@ -292,6 +296,7 @@ macro(_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) set(NO_DEPRECATED_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_NO_DEPRECATED_MACRO_NAME}) endif() + string(MAKE_C_IDENTIFIER ${NO_DEPRECATED_MACRO_NAME} NO_DEPRECATED_MACRO_NAME) set(INCLUDE_GUARD_NAME "${EXPORT_MACRO_NAME}_H") @@ -300,6 +305,7 @@ macro(_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) if(NOT EXPORT_IMPORT_CONDITION) set(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY}_EXPORTS) endif() + string(MAKE_C_IDENTIFIER ${EXPORT_IMPORT_CONDITION} EXPORT_IMPORT_CONDITION) configure_file("${_GENERATE_EXPORT_HEADER_MODULE_DIR}/exportheader.cmake.in" "${EXPORT_FILE_NAME}" @ONLY) @@ -307,11 +313,9 @@ endmacro() function(GENERATE_EXPORT_HEADER TARGET_LIBRARY) get_property(type TARGET ${TARGET_LIBRARY} PROPERTY TYPE) - if(${type} STREQUAL "MODULE") - message(WARNING "This macro should not be used with libraries of type MODULE") - return() - endif() - if(NOT ${type} STREQUAL "STATIC_LIBRARY" AND NOT ${type} STREQUAL "SHARED_LIBRARY") + if(NOT ${type} STREQUAL "STATIC_LIBRARY" + AND NOT ${type} STREQUAL "SHARED_LIBRARY" + AND NOT ${type} STREQUAL "MODULE_LIBRARY") message(WARNING "This macro can only be used with libraries") return() endif() diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index 18f449dda..9e89788fe 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -635,7 +635,6 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa set(gp_regex_fallback "") set(gp_regex_cmp_count 1) set(gp_tool_known 1) - set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE. endif() if("${gp_tool}" STREQUAL "objdump") diff --git a/Modules/NSIS.template.in b/Modules/NSIS.template.in index 59a444bde..76310af31 100644 --- a/Modules/NSIS.template.in +++ b/Modules/NSIS.template.in @@ -916,7 +916,9 @@ Function .onInit ;Run the uninstaller uninst: ClearErrors - ExecWait '$0 _?=$INSTDIR' ;Do not copy the uninstaller to a temp file + StrLen $2 "\Uninstall.exe" + StrCpy $3 $0 -$2 # remove "\Uninstall.exe" from UninstallString to get path + ExecWait '$0 _?=$3' ;Do not copy the uninstaller to a temp file IfErrors uninst_failed inst uninst_failed: diff --git a/Modules/Platform/Darwin-Absoft-Fortran.cmake b/Modules/Platform/Darwin-Absoft-Fortran.cmake index beb41a3b8..dc62b0dce 100644 --- a/Modules/Platform/Darwin-Absoft-Fortran.cmake +++ b/Modules/Platform/Darwin-Absoft-Fortran.cmake @@ -1 +1,18 @@ +#============================================================================= +# Copyright 2011 Kitware, Inc. +# Copyright 2013 OpenGamma Ltd. <graham@opengamma.com> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + set(CMAKE_Fortran_VERBOSE_FLAG "-X -v") # Runs gcc under the hood. + +set(CMAKE_Fortran_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set(CMAKE_Fortran_OSX_CURRENT_VERSION_FLAG "-current_version ") diff --git a/Modules/Platform/Darwin-GNU-Fortran.cmake b/Modules/Platform/Darwin-GNU-Fortran.cmake index 8e8acc377..f4b509a13 100644 --- a/Modules/Platform/Darwin-GNU-Fortran.cmake +++ b/Modules/Platform/Darwin-GNU-Fortran.cmake @@ -1,2 +1,19 @@ +#============================================================================= +# Copyright 2009 Kitware, Inc. +# Copyright 2013 OpenGamma Ltd. <graham@opengamma.com> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + include(Platform/Darwin-GNU) __darwin_compiler_gnu(Fortran) + +set(CMAKE_Fortran_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set(CMAKE_Fortran_OSX_CURRENT_VERSION_FLAG "-current_version ") diff --git a/Modules/Platform/Darwin-Intel-Fortran.cmake b/Modules/Platform/Darwin-Intel-Fortran.cmake new file mode 100644 index 000000000..6bd45f15c --- /dev/null +++ b/Modules/Platform/Darwin-Intel-Fortran.cmake @@ -0,0 +1,15 @@ +#============================================================================= +# Copyright 2013 OpenGamma Ltd. <graham@opengamma.com> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +set(CMAKE_Fortran_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set(CMAKE_Fortran_OSX_CURRENT_VERSION_FLAG "-current_version ") diff --git a/Modules/Platform/Darwin-NAG-Fortran.cmake b/Modules/Platform/Darwin-NAG-Fortran.cmake index 933f9e1a2..4c28e625c 100644 --- a/Modules/Platform/Darwin-NAG-Fortran.cmake +++ b/Modules/Platform/Darwin-NAG-Fortran.cmake @@ -1,5 +1,26 @@ +#============================================================================= +# Copyright 2010 Kitware, Inc. +# Copyright 2013 OpenGamma Ltd. <graham@opengamma.com> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + set(CMAKE_Fortran_VERBOSE_FLAG "-Wl,-v") # Runs gcc under the hood. # Need -fpp explicitly on case-insensitive filesystem. set(CMAKE_Fortran_COMPILE_OBJECT "<CMAKE_Fortran_COMPILER> -fpp -o <OBJECT> <DEFINES> <FLAGS> -c <SOURCE>") + +set(CMAKE_Fortran_OSX_COMPATIBILITY_VERSION_FLAG "-Wl,-compatibility_version -Wl,") +set(CMAKE_Fortran_OSX_CURRENT_VERSION_FLAG "-Wl,-current_version -Wl,") +set(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-Wl,-shared") +set(CMAKE_SHARED_LIBRARY_SONAME_Fortran_FLAG "-Wl,-install_name -Wl,") +set(CMAKE_Fortran_CREATE_SHARED_LIBRARY + "<CMAKE_Fortran_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS> <LINK_FLAGS> -o <TARGET> <SONAME_FLAG><TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>") diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index 2e6b71e36..72844b531 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -30,6 +30,11 @@ set(CMAKE_SHARED_MODULE_SUFFIX ".so") set(CMAKE_MODULE_EXISTS 1) set(CMAKE_DL_LIBS "") +# Enable rpath support for 10.5 and greater where it is known to work. +if("${DARWIN_MAJOR_VERSION}" GREATER 8) + set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,") +endif() + set(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") set(CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") set(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") @@ -127,9 +132,25 @@ elseif("${CMAKE_GENERATOR}" MATCHES Xcode # specially named SDKs. set(_CMAKE_OSX_SDKS_VER_SUFFIX_10.4 "u") set(_CMAKE_OSX_SDKS_VER_SUFFIX_10.3 ".9") - set(_CMAKE_OSX_SDKS_VER ${_CURRENT_OSX_VERSION}${_CMAKE_OSX_SDKS_VER_SUFFIX_${_CURRENT_OSX_VERSION}}) - set(_CMAKE_OSX_SYSROOT_DEFAULT - "${_CMAKE_OSX_SDKS_DIR}/MacOSX${_CMAKE_OSX_SDKS_VER}.sdk") + if(CMAKE_OSX_DEPLOYMENT_TARGET) + set(_CMAKE_OSX_SDKS_VER ${CMAKE_OSX_DEPLOYMENT_TARGET}${_CMAKE_OSX_SDKS_VER_SUFFIX_${CMAKE_OSX_DEPLOYMENT_TARGET}}) + set(_CMAKE_OSX_SYSROOT_CHECK "${_CMAKE_OSX_SDKS_DIR}/MacOSX${_CMAKE_OSX_SDKS_VER}.sdk") + if(IS_DIRECTORY "${_CMAKE_OSX_SYSROOT_CHECK}") + set(_CMAKE_OSX_SYSROOT_DEFAULT "${_CMAKE_OSX_SYSROOT_CHECK}") + else() + set(_CMAKE_OSX_SDKS_VER ${_CURRENT_OSX_VERSION}${_CMAKE_OSX_SDKS_VER_SUFFIX_${_CURRENT_OSX_VERSION}}) + set(_CMAKE_OSX_SYSROOT_DEFAULT "${_CMAKE_OSX_SDKS_DIR}/MacOSX${_CMAKE_OSX_SDKS_VER}.sdk") + message(WARNING + "CMAKE_OSX_DEPLOYMENT_TARGET is '${CMAKE_OSX_DEPLOYMENT_TARGET}' " + "but the matching SDK does not exist at:\n \"${_CMAKE_OSX_SYSROOT_CHECK}\"\n" + "Instead using SDK:\n \"${_CMAKE_OSX_SYSROOT_DEFAULT}\"\n" + "matching the host OS X version." + ) + endif() + else() + set(_CMAKE_OSX_SDKS_VER ${_CURRENT_OSX_VERSION}${_CMAKE_OSX_SDKS_VER_SUFFIX_${_CURRENT_OSX_VERSION}}) + set(_CMAKE_OSX_SYSROOT_DEFAULT "${_CMAKE_OSX_SDKS_DIR}/MacOSX${_CMAKE_OSX_SDKS_VER}.sdk") + endif() else() # Assume developer files are in root (such as Xcode 4.5 command-line tools). set(_CMAKE_OSX_SYSROOT_DEFAULT "") @@ -207,12 +228,8 @@ if("${CMAKE_BACKWARDS_COMPATIBILITY}" MATCHES "^1\\.[0-6]$") "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined suppress") endif() -if(NOT XCODE) - # Enable shared library versioning. This flag is not actually referenced - # but the fact that the setting exists will cause the generators to support - # soname computation. - set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") -endif() +# Enable shared library versioning. +set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") # Xcode does not support -isystem yet. if(XCODE) @@ -277,6 +294,15 @@ endif() # set up the default search directories for frameworks set(CMAKE_SYSTEM_FRAMEWORK_PATH ~/Library/Frameworks + ) +if(_CMAKE_OSX_SYSROOT_PATH) + list(APPEND CMAKE_SYSTEM_FRAMEWORK_PATH + ${_CMAKE_OSX_SYSROOT_PATH}/Library/Frameworks + ${_CMAKE_OSX_SYSROOT_PATH}/Network/Library/Frameworks + ${_CMAKE_OSX_SYSROOT_PATH}/System/Library/Frameworks + ) +endif() +list(APPEND CMAKE_SYSTEM_FRAMEWORK_PATH /Library/Frameworks /Network/Library/Frameworks /System/Library/Frameworks) @@ -321,6 +347,12 @@ set(CMAKE_SYSTEM_APPBUNDLE_PATH unset(_apps_paths) include(Platform/UnixPaths) +if(_CMAKE_OSX_SYSROOT_PATH AND EXISTS ${_CMAKE_OSX_SYSROOT_PATH}/usr/include) + list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${_CMAKE_OSX_SYSROOT_PATH}/usr) + foreach(lang C CXX) + list(APPEND CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES ${_CMAKE_OSX_SYSROOT_PATH}/usr/include) + endforeach() +endif() list(APPEND CMAKE_SYSTEM_PREFIX_PATH /sw # Fink /opt/local # MacPorts diff --git a/Modules/Platform/Windows-Embarcadero.cmake b/Modules/Platform/Windows-Embarcadero.cmake index 307230e34..26b3c0cab 100644 --- a/Modules/Platform/Windows-Embarcadero.cmake +++ b/Modules/Platform/Windows-Embarcadero.cmake @@ -78,23 +78,24 @@ set (CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO_INIT ${CMAKE_SHARED_LINKER_FLAGS_R macro(__embarcadero_language lang) set(CMAKE_${lang}_COMPILE_OPTIONS_DLL "${_tD}") # Note: This variable is a ';' separated list set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "${_tD}") # ... while this is a space separated string. + set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1) # compile a source file into an object file # place <DEFINES> outside the response file because Borland refuses # to parse quotes from the response file. set(CMAKE_${lang}_COMPILE_OBJECT - "<CMAKE_${lang}_COMPILER> ${_tR} <DEFINES> ${CMAKE_START_TEMP_FILE}-DWIN32 -o<OBJECT> <FLAGS> ${_COMPILE_${lang}} <SOURCE>${CMAKE_END_TEMP_FILE}" + "<CMAKE_${lang}_COMPILER> ${_tR} <DEFINES> -DWIN32 -o<OBJECT> <FLAGS> ${_COMPILE_${lang}} <SOURCE>" ) set(CMAKE_${lang}_LINK_EXECUTABLE - "<CMAKE_${lang}_COMPILER> ${_tR} -e<TARGET> ${CMAKE_START_TEMP_FILE}<LINK_FLAGS> <FLAGS> <LINK_LIBRARIES> <OBJECTS>${CMAKE_END_TEMP_FILE}" + "<CMAKE_${lang}_COMPILER> ${_tR} -e<TARGET> <LINK_FLAGS> <FLAGS> ${CMAKE_START_TEMP_FILE} <LINK_LIBRARIES> <OBJECTS>${CMAKE_END_TEMP_FILE}" # "implib -c -w <TARGET_IMPLIB> <TARGET>" ) # place <DEFINES> outside the response file because Borland refuses # to parse quotes from the response file. set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE - "cpp32 <DEFINES> ${CMAKE_START_TEMP_FILE}-DWIN32 <FLAGS> -o<PREPROCESSED_SOURCE> ${_COMPILE_${lang}} <SOURCE>${CMAKE_END_TEMP_FILE}" + "cpp32 <DEFINES> -DWIN32 <FLAGS> -o<PREPROCESSED_SOURCE> ${_COMPILE_${lang}} <SOURCE>" ) # Borland >= 5.6 allows -P option for cpp32, <= 5.5 does not diff --git a/Modules/Platform/Windows-Intel.cmake b/Modules/Platform/Windows-Intel.cmake index 8a9d630f6..69a7f2ff0 100644 --- a/Modules/Platform/Windows-Intel.cmake +++ b/Modules/Platform/Windows-Intel.cmake @@ -81,7 +81,7 @@ endif() macro(__windows_compiler_intel lang) set(CMAKE_${lang}_COMPILE_OBJECT - "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} /Fo<OBJECT> <DEFINES> <FLAGS> -c <SOURCE>${CMAKE_END_TEMP_FILE}") + "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} /Fo<OBJECT> /Fd<OBJECT_DIR>/ <DEFINES> <FLAGS> -c <SOURCE>${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> > <PREPROCESSED_SOURCE> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <DEFINES> <FLAGS> -E <SOURCE>${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 1) @@ -91,7 +91,7 @@ macro(__windows_compiler_intel lang) set(CMAKE_${lang}_CREATE_SHARED_MODULE "${CMAKE_${lang}_CREATE_SHARED_LIBRARY}") set(CMAKE_${lang}_COMPILER_LINKER_OPTION_FLAG_EXECUTABLE "/link") set(CMAKE_${lang}_LINK_EXECUTABLE - "<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} <FLAGS> /Fe<TARGET> <OBJECTS> /link /implib:<TARGET_IMPLIB> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}") + "<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} <FLAGS> /Fe<TARGET> <OBJECTS> /link /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_FLAGS_INIT "/DWIN32 /D_WINDOWS /W3 /Zm1000${_FLAGS_${lang}}") set(CMAKE_${lang}_FLAGS_DEBUG_INIT "/D_DEBUG /MDd /Zi /Od /RTC1") set(CMAKE_${lang}_FLAGS_MINSIZEREL_INIT "/DNDEBUG /MD /O1") diff --git a/Modules/Platform/Windows-MSVC-C.cmake b/Modules/Platform/Windows-MSVC-C.cmake index e81df9f83..cbe1586e1 100644 --- a/Modules/Platform/Windows-MSVC-C.cmake +++ b/Modules/Platform/Windows-MSVC-C.cmake @@ -1,2 +1,5 @@ include(Platform/Windows-MSVC) +if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 18.0) + set(_FS_C " /FS") +endif() __windows_compiler_msvc(C) diff --git a/Modules/Platform/Windows-MSVC-CXX.cmake b/Modules/Platform/Windows-MSVC-CXX.cmake index fdd1dae05..0e8500532 100644 --- a/Modules/Platform/Windows-MSVC-CXX.cmake +++ b/Modules/Platform/Windows-MSVC-CXX.cmake @@ -1,3 +1,6 @@ include(Platform/Windows-MSVC) set(_COMPILE_CXX " /TP") +if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0) + set(_FS_CXX " /FS") +endif() __windows_compiler_msvc(CXX) diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index e03b60115..6e02e4aca 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -22,7 +22,7 @@ set(CMAKE_LIBRARY_PATH_FLAG "-LIBPATH:") set(CMAKE_LINK_LIBRARY_FLAG "") set(MSVC 1) -# hack: if a new cmake (which uses CMAKE__LINKER) runs on an old build tree +# hack: if a new cmake (which uses CMAKE_LINKER) runs on an old build tree # (where link was hardcoded) and where CMAKE_LINKER isn't in the cache # and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun) # hardcode CMAKE_LINKER here to link, so it behaves as it did before, Alex @@ -52,9 +52,6 @@ if(CMAKE_GENERATOR MATCHES "Visual Studio 6") endif() if(NOT CMAKE_NO_BUILD_TYPE AND CMAKE_GENERATOR MATCHES "Visual Studio") set (CMAKE_NO_BUILD_TYPE 1) - set (CMAKE_CONFIGURATION_TYPES "Debug;Release;MinSizeRel;RelWithDebInfo" CACHE STRING - "Semicolon separated list of supported configuration types, only supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything else will be ignored.") - mark_as_advanced(CMAKE_CONFIGURATION_TYPES) endif() # make sure to enable languages after setting configuration types @@ -127,8 +124,15 @@ endif() set(CMAKE_BUILD_TYPE_INIT Debug) if(WINCE) - string(TOUPPER "${MSVC_C_ARCHITECTURE_ID}" _MSVC_C_ARCHITECTURE_ID_UPPER) - string(TOUPPER "${MSVC_CXX_ARCHITECTURE_ID}" _MSVC_CXX_ARCHITECTURE_ID_UPPER) + foreach(lang C CXX) + set(_MSVC_${lang}_ARCHITECTURE_FAMILY "${MSVC_${lang}_ARCHITECTURE_ID}") + if(_MSVC_${lang}_ARCHITECTURE_FAMILY STREQUAL "THUMB") + set(_MSVC_${lang}_ARCHITECTURE_FAMILY "ARM") + elseif(_MSVC_${lang}_ARCHITECTURE_FAMILY MATCHES "^SH") + set(_MSVC_${lang}_ARCHITECTURE_FAMILY "SHx") + endif() + string(TOUPPER "${_MSVC_${lang}_ARCHITECTURE_FAMILY}" _MSVC_${lang}_ARCHITECTURE_FAMILY_UPPER) + endforeach() if("${CMAKE_SYSTEM_VERSION}" MATCHES "^([0-9]+)\\.([0-9]+)") math(EXPR _CE_VERSION "${CMAKE_MATCH_1}*100 + ${CMAKE_MATCH_2}") @@ -139,13 +143,17 @@ if(WINCE) endif() set(_PLATFORM_DEFINES "/D_WIN32_WCE=0x${_CE_VERSION} /DUNDER_CE") - set(_PLATFORM_DEFINES_C " /D${MSVC_C_ARCHITECTURE_ID} /D_${_MSVC_C_ARCHITECTURE_ID_UPPER}_") - set(_PLATFORM_DEFINES_CXX " /D${MSVC_CXX_ARCHITECTURE_ID} /D_${_MSVC_CXX_ARCHITECTURE_ID_UPPER}_") + set(_PLATFORM_DEFINES_C " /D${_MSVC_C_ARCHITECTURE_FAMILY} /D_${_MSVC_C_ARCHITECTURE_FAMILY_UPPER}_") + set(_PLATFORM_DEFINES_CXX " /D${_MSVC_CXX_ARCHITECTURE_FAMILY} /D_${_MSVC_CXX_ARCHITECTURE_FAMILY_UPPER}_") set(_RTC1 "") set(_FLAGS_CXX " /GR /EHsc") - set(CMAKE_C_STANDARD_LIBRARIES_INIT "coredll.lib corelibc.lib ole32.lib oleaut32.lib uuid.lib commctrl.lib") + set(CMAKE_C_STANDARD_LIBRARIES_INIT "coredll.lib ole32.lib oleaut32.lib uuid.lib commctrl.lib") set(CMAKE_EXE_LINKER_FLAGS_INIT "${CMAKE_EXE_LINKER_FLAGS_INIT} /NODEFAULTLIB:libc.lib /NODEFAULTLIB:oldnames.lib") + + if (MSVC_VERSION LESS 1600) + set(CMAKE_C_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT} corelibc.lib") + endif () else() set(_PLATFORM_DEFINES "/DWIN32") @@ -174,13 +182,6 @@ set(_MACHINE_ARCH_FLAG ${MSVC_C_ARCHITECTURE_ID}) if(NOT _MACHINE_ARCH_FLAG) set(_MACHINE_ARCH_FLAG ${MSVC_CXX_ARCHITECTURE_ID}) endif() -if(WINCE) - if(_MACHINE_ARCH_FLAG MATCHES "ARM") - set(_MACHINE_ARCH_FLAG "THUMB") - elseif(_MACHINE_ARCH_FLAG MATCHES "SH") - set(_MACHINE_ARCH_FLAG "SH4") - endif() -endif() set (CMAKE_EXE_LINKER_FLAGS_INIT "${CMAKE_EXE_LINKER_FLAGS_INIT} /machine:${_MACHINE_ARCH_FLAG}") @@ -231,16 +232,15 @@ macro(__windows_compiler_msvc lang) set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_LINKER> /lib ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ") set(CMAKE_${lang}_COMPILE_OBJECT - "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <FLAGS> <DEFINES> /Fo<OBJECT> /Fd<TARGET_PDB> -c <SOURCE>${CMAKE_END_TEMP_FILE}") + "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <FLAGS> <DEFINES> /Fo<OBJECT> /Fd<OBJECT_DIR>/${_FS_${lang}} -c <SOURCE>${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> > <PREPROCESSED_SOURCE> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <FLAGS> <DEFINES> -E <SOURCE>${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <FLAGS> <DEFINES> /FoNUL /FAs /Fa<ASSEMBLY_SOURCE> /c <SOURCE>${CMAKE_END_TEMP_FILE}") - set(CMAKE_${lang}_COMPILER_LINKER_OPTION_FLAG_EXECUTABLE "/link") set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 1) set(CMAKE_${lang}_LINK_EXECUTABLE - "${_CMAKE_VS_LINK_EXE}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} <FLAGS> /Fe<TARGET> /Fd<TARGET_PDB> <OBJECTS> /link /implib:<TARGET_IMPLIB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}") + "${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_FLAGS_INIT "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_${lang}} /D_WINDOWS /W3${_FLAGS_${lang}}") set(CMAKE_${lang}_FLAGS_DEBUG_INIT "/D_DEBUG /MDd /Zi /Ob0 /Od ${_RTC1}") diff --git a/Modules/Platform/Windows-df.cmake b/Modules/Platform/Windows-df.cmake index 7e2ac9fe4..8dfb61057 100644 --- a/Modules/Platform/Windows-df.cmake +++ b/Modules/Platform/Windows-df.cmake @@ -38,8 +38,6 @@ if(CMAKE_GENERATOR MATCHES "Visual Studio 6") endif() if(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR CMAKE_GENERATOR MATCHES "Visual Studio 8") set (CMAKE_NO_BUILD_TYPE 1) - set (CMAKE_CONFIGURATION_TYPES "Debug;Release;MinSizeRel;RelWithDebInfo" CACHE STRING - "Semicolon separated list of supported configuration types, only supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything else will be ignored.") endif() # does the compiler support pdbtype and is it the newer compiler diff --git a/Modules/Platform/WindowsPaths.cmake b/Modules/Platform/WindowsPaths.cmake index bd31da021..fc921d793 100644 --- a/Modules/Platform/WindowsPaths.cmake +++ b/Modules/Platform/WindowsPaths.cmake @@ -77,10 +77,12 @@ list(APPEND CMAKE_SYSTEM_PREFIX_PATH "${_CMAKE_INSTALL_DIR}") list(APPEND CMAKE_SYSTEM_PREFIX_PATH # Project install destination. "${CMAKE_INSTALL_PREFIX}" + ) +if(CMAKE_CROSSCOMPILING AND NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") # MinGW (useful when cross compiling from linux with CMAKE_FIND_ROOT_PATH set) - / - ) + list(APPEND CMAKE_SYSTEM_PREFIX_PATH /) +endif() list(APPEND CMAKE_SYSTEM_INCLUDE_PATH ) diff --git a/Modules/Qt4Macros.cmake b/Modules/Qt4Macros.cmake index f6c8476a5..f1aedd743 100644 --- a/Modules/Qt4Macros.cmake +++ b/Modules/Qt4Macros.cmake @@ -21,15 +21,20 @@ ###################################### -macro (QT4_EXTRACT_OPTIONS _qt4_files _qt4_options) +macro (QT4_EXTRACT_OPTIONS _qt4_files _qt4_options _qt4_target) set(${_qt4_files}) set(${_qt4_options}) set(_QT4_DOING_OPTIONS FALSE) + set(_QT4_DOING_TARGET FALSE) foreach(_currentArg ${ARGN}) - if ("${_currentArg}" STREQUAL "OPTIONS") + if ("x${_currentArg}" STREQUAL "xOPTIONS") set(_QT4_DOING_OPTIONS TRUE) + elseif ("x${_currentArg}" STREQUAL "xTARGET") + set(_QT4_DOING_TARGET TRUE) else () - if(_QT4_DOING_OPTIONS) + if(_QT4_DOING_TARGET) + set(${_qt4_target} "${_currentArg}") + elseif(_QT4_DOING_OPTIONS) list(APPEND ${_qt4_options} "${_currentArg}") else() list(APPEND ${_qt4_files} "${_currentArg}") @@ -92,34 +97,46 @@ endmacro() # helper macro to set up a moc rule -macro (QT4_CREATE_MOC_COMMAND infile outfile moc_flags moc_options) +macro (QT4_CREATE_MOC_COMMAND infile outfile moc_flags moc_options moc_target) # For Windows, create a parameters file to work around command line length limit - if (WIN32) - # Pass the parameters in a file. Set the working directory to - # be that containing the parameters file and reference it by - # just the file name. This is necessary because the moc tool on - # MinGW builds does not seem to handle spaces in the path to the - # file given with the @ syntax. - get_filename_component(_moc_outfile_name "${outfile}" NAME) - get_filename_component(_moc_outfile_dir "${outfile}" PATH) - if(_moc_outfile_dir) - set(_moc_working_dir WORKING_DIRECTORY ${_moc_outfile_dir}) - endif() - set (_moc_parameters_file ${outfile}_parameters) - set (_moc_parameters ${moc_flags} ${moc_options} -o "${outfile}" "${infile}") - string (REPLACE ";" "\n" _moc_parameters "${_moc_parameters}") - file (WRITE ${_moc_parameters_file} "${_moc_parameters}") - add_custom_command(OUTPUT ${outfile} - COMMAND ${QT_MOC_EXECUTABLE} @${_moc_outfile_name}_parameters - DEPENDS ${infile} - ${_moc_working_dir} - VERBATIM) - else () - add_custom_command(OUTPUT ${outfile} - COMMAND ${QT_MOC_EXECUTABLE} - ARGS ${moc_flags} ${moc_options} -o ${outfile} ${infile} - DEPENDS ${infile} VERBATIM) - endif () + # Pass the parameters in a file. Set the working directory to + # be that containing the parameters file and reference it by + # just the file name. This is necessary because the moc tool on + # MinGW builds does not seem to handle spaces in the path to the + # file given with the @ syntax. + get_filename_component(_moc_outfile_name "${outfile}" NAME) + get_filename_component(_moc_outfile_dir "${outfile}" PATH) + if(_moc_outfile_dir) + set(_moc_working_dir WORKING_DIRECTORY ${_moc_outfile_dir}) + endif() + set (_moc_parameters_file ${outfile}_parameters) + set (_moc_parameters ${moc_flags} ${moc_options} -o "${outfile}" "${infile}") + string (REPLACE ";" "\n" _moc_parameters "${_moc_parameters}") + + if(moc_target) + set(targetincludes "$<TARGET_PROPERTY:${moc_target},INCLUDE_DIRECTORIES>") + set(targetdefines "$<TARGET_PROPERTY:${moc_target},COMPILE_DEFINITIONS>") + + set(targetincludes "$<$<BOOL:${targetincludes}>:-I$<JOIN:${targetincludes},\n-I>\n>") + set(targetdefines "$<$<BOOL:${targetdefines}>:-D$<JOIN:${targetdefines},\n-D>\n>") + + file (GENERATE + OUTPUT ${_moc_parameters_file} + CONTENT "${targetdefines}${targetincludes}${_moc_parameters}\n" + ) + + set(targetincludes) + set(targetdefines) + else() + file(WRITE ${_moc_parameters_file} "${_moc_parameters}\n") + endif() + + set(_moc_extra_parameters_file @${_moc_parameters_file}) + add_custom_command(OUTPUT ${outfile} + COMMAND ${QT_MOC_EXECUTABLE} ${_moc_extra_parameters_file} + DEPENDS ${infile} + ${_moc_working_dir} + VERBATIM) endmacro () @@ -131,7 +148,11 @@ macro (QT4_GENERATE_MOC infile outfile ) if(NOT IS_ABSOLUTE "${outfile}") set(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}") endif() - QT4_CREATE_MOC_COMMAND(${abs_infile} ${_outfile} "${moc_flags}" "") + + if ("x${ARGV2}" STREQUAL "xTARGET") + set(moc_target ${ARGV3}) + endif() + QT4_CREATE_MOC_COMMAND(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}") set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC TRUE) # dont run automoc on this file endmacro () @@ -141,12 +162,12 @@ endmacro () macro (QT4_WRAP_CPP outfiles ) # get include dirs QT4_GET_MOC_FLAGS(moc_flags) - QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN}) + QT4_EXTRACT_OPTIONS(moc_files moc_options moc_target ${ARGN}) foreach (it ${moc_files}) get_filename_component(it ${it} ABSOLUTE) QT4_MAKE_OUTPUT_FILE(${it} moc_ cxx outfile) - QT4_CREATE_MOC_COMMAND(${it} ${outfile} "${moc_flags}" "${moc_options}") + QT4_CREATE_MOC_COMMAND(${it} ${outfile} "${moc_flags}" "${moc_options}" "${moc_target}") set(${outfiles} ${${outfiles}} ${outfile}) endforeach() @@ -156,7 +177,7 @@ endmacro () # QT4_WRAP_UI(outfiles inputfile ... ) macro (QT4_WRAP_UI outfiles ) - QT4_EXTRACT_OPTIONS(ui_files ui_options ${ARGN}) + QT4_EXTRACT_OPTIONS(ui_files ui_options ui_target ${ARGN}) foreach (it ${ui_files}) get_filename_component(outfile ${it} NAME_WE) @@ -175,7 +196,7 @@ endmacro () # QT4_ADD_RESOURCES(outfiles inputfile ... ) macro (QT4_ADD_RESOURCES outfiles ) - QT4_EXTRACT_OPTIONS(rcc_files rcc_options ${ARGN}) + QT4_EXTRACT_OPTIONS(rcc_files rcc_options rcc_target ${ARGN}) foreach (it ${rcc_files}) get_filename_component(outfilename ${it} NAME_WE) @@ -270,7 +291,7 @@ endmacro() macro(QT4_GENERATE_DBUS_INTERFACE _header) # _customName OPTIONS -some -options ) - QT4_EXTRACT_OPTIONS(_customName _qt4_dbus_options ${ARGN}) + QT4_EXTRACT_OPTIONS(_customName _qt4_dbus_options _qt4_dbus_target ${ARGN}) get_filename_component(_in_file ${_header} ABSOLUTE) get_filename_component(_basename ${_header} NAME_WE) @@ -333,6 +354,17 @@ endmacro() macro(QT4_AUTOMOC) + if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.11) + if(CMAKE_WARN_DEPRECATED) + set(messageType WARNING) + endif() + if(CMAKE_ERROR_DEPRECATED) + set(messageType FATAL_ERROR) + endif() + if(messageType) + message(${messageType} "The qt4_automoc macro is obsolete. Use the CMAKE_AUTOMOC feature instead.") + endif() + endif() QT4_GET_MOC_FLAGS(_moc_INCS) set(_matching_FILES ) @@ -366,7 +398,7 @@ macro(QT4_AUTOMOC) set(_header ${_abs_PATH}/${_basename}.h) endif() set(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_current_MOC}) - QT4_CREATE_MOC_COMMAND(${_header} ${_moc} "${_moc_INCS}" "") + QT4_CREATE_MOC_COMMAND(${_header} ${_moc} "${_moc_INCS}" "" "") MACRO_ADD_FILE_DEPENDENCIES(${_abs_FILE} ${_moc}) endforeach () endif() @@ -376,7 +408,7 @@ endmacro() macro(QT4_CREATE_TRANSLATION _qm_files) - QT4_EXTRACT_OPTIONS(_lupdate_files _lupdate_options ${ARGN}) + QT4_EXTRACT_OPTIONS(_lupdate_files _lupdate_options _lupdate_target ${ARGN}) set(_my_sources) set(_my_dirs) set(_my_tsfiles) @@ -443,6 +475,17 @@ macro(QT4_ADD_TRANSLATION _qm_files) endmacro() function(qt4_use_modules _target _link_type) + if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.11) + if(CMAKE_WARN_DEPRECATED) + set(messageType WARNING) + endif() + if(CMAKE_ERROR_DEPRECATED) + set(messageType FATAL_ERROR) + endif() + if(messageType) + message(${messageType} "The qt4_use_modules function is obsolete. Use target_link_libraries with IMPORTED targets instead.") + endif() + endif() if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE") set(modules ${ARGN}) set(link_type ${_link_type}) diff --git a/Modules/SelectLibraryConfigurations.cmake b/Modules/SelectLibraryConfigurations.cmake index 5bca064f5..297e1d3bd 100644 --- a/Modules/SelectLibraryConfigurations.cmake +++ b/Modules/SelectLibraryConfigurations.cmake @@ -3,16 +3,18 @@ # This macro takes a library base name as an argument, and will choose good # values for basename_LIBRARY, basename_LIBRARIES, basename_LIBRARY_DEBUG, and # basename_LIBRARY_RELEASE depending on what has been found and set. If only -# basename_LIBRARY_RELEASE is defined, basename_LIBRARY, basename_LIBRARY_DEBUG, -# and basename_LIBRARY_RELEASE will be set to the release value. If only -# basename_LIBRARY_DEBUG is defined, then basename_LIBRARY, -# basename_LIBRARY_DEBUG and basename_LIBRARY_RELEASE will take the debug value. +# basename_LIBRARY_RELEASE is defined, basename_LIBRARY will be set to the +# release value, and basename_LIBRARY_DEBUG will be set to +# basename_LIBRARY_DEBUG-NOTFOUND. If only basename_LIBRARY_DEBUG is defined, +# then basename_LIBRARY will take the debug value, and basename_LIBRARY_RELEASE +# will be set to basename_LIBRARY_RELEASE-NOTFOUND. # # If the generator supports configuration types, then basename_LIBRARY and # basename_LIBRARIES will be set with debug and optimized flags specifying the # library to be used for the given configuration. If no build type has been set # or the generator in use does not support configuration types, then -# basename_LIBRARY and basename_LIBRARIES will take only the release values. +# basename_LIBRARY and basename_LIBRARIES will take only the release value, or +# the debug value if the release one is not set. #============================================================================= # Copyright 2009 Will Dicharry <wdicharry@stellarscience.com> @@ -31,57 +33,41 @@ # This macro was adapted from the FindQt4 CMake module and is maintained by Will # Dicharry <wdicharry@stellarscience.com>. -# Utility macro to check if one variable exists while another doesn't, and set -# one that doesn't exist to the one that exists. -macro( _set_library_name basename GOOD BAD ) - if( ${basename}_LIBRARY_${GOOD} AND NOT ${basename}_LIBRARY_${BAD} ) - set( ${basename}_LIBRARY_${BAD} ${${basename}_LIBRARY_${GOOD}} ) - set( ${basename}_LIBRARY ${${basename}_LIBRARY_${GOOD}} ) - set( ${basename}_LIBRARIES ${${basename}_LIBRARY_${GOOD}} ) - endif() -endmacro() - macro( select_library_configurations basename ) - # if only the release version was found, set the debug to be the release - # version. - _set_library_name( ${basename} RELEASE DEBUG ) - # if only the debug version was found, set the release value to be the - # debug value. - _set_library_name( ${basename} DEBUG RELEASE ) - - # Set a default case, which will come into effect if - # -no build type is set and the generator only supports one build type - # at a time (i.e. CMAKE_CONFIGURATION_TYPES is false) - # -${basename}_LIBRARY_DEBUG and ${basename}_LIBRARY_RELEASE are the same - # -${basename}_LIBRARY_DEBUG and ${basename}_LIBRARY_RELEASE are both empty - set( ${basename}_LIBRARY ${${basename}_LIBRARY_RELEASE} ) - set( ${basename}_LIBRARIES ${${basename}_LIBRARY_RELEASE} ) + if(NOT ${basename}_LIBRARY_RELEASE) + set(${basename}_LIBRARY_RELEASE "${basename}_LIBRARY_RELEASE-NOTFOUND" CACHE FILEPATH "Path to a library.") + endif() + if(NOT ${basename}_LIBRARY_DEBUG) + set(${basename}_LIBRARY_DEBUG "${basename}_LIBRARY_DEBUG-NOTFOUND" CACHE FILEPATH "Path to a library.") + endif() if( ${basename}_LIBRARY_DEBUG AND ${basename}_LIBRARY_RELEASE AND - NOT ${basename}_LIBRARY_DEBUG STREQUAL ${basename}_LIBRARY_RELEASE ) + NOT ${basename}_LIBRARY_DEBUG STREQUAL ${basename}_LIBRARY_RELEASE AND + ( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) ) # if the generator supports configuration types or CMAKE_BUILD_TYPE # is set, then set optimized and debug options. - if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) - set( ${basename}_LIBRARY "" ) - foreach( _libname IN LISTS ${basename}_LIBRARY_RELEASE ) - list( APPEND ${basename}_LIBRARY optimized "${_libname}" ) - endforeach() - foreach( _libname IN LISTS ${basename}_LIBRARY_DEBUG ) - list( APPEND ${basename}_LIBRARY debug "${_libname}" ) - endforeach() - set( ${basename}_LIBRARIES "${${basename}_LIBRARY}" ) - endif() + set( ${basename}_LIBRARY "" ) + foreach( _libname IN LISTS ${basename}_LIBRARY_RELEASE ) + list( APPEND ${basename}_LIBRARY optimized "${_libname}" ) + endforeach() + foreach( _libname IN LISTS ${basename}_LIBRARY_DEBUG ) + list( APPEND ${basename}_LIBRARY debug "${_libname}" ) + endforeach() + elseif( ${basename}_LIBRARY_RELEASE ) + set( ${basename}_LIBRARY ${${basename}_LIBRARY_RELEASE} ) + elseif( ${basename}_LIBRARY_DEBUG ) + set( ${basename}_LIBRARY ${${basename}_LIBRARY_DEBUG} ) + else() + set( ${basename}_LIBRARY "${basename}_LIBRARY-NOTFOUND") endif() - set( ${basename}_LIBRARY ${${basename}_LIBRARY} CACHE FILEPATH - "The ${basename} library" ) + set( ${basename}_LIBRARIES "${${basename}_LIBRARY}" ) if( ${basename}_LIBRARY ) set( ${basename}_FOUND TRUE ) endif() - mark_as_advanced( ${basename}_LIBRARY - ${basename}_LIBRARY_RELEASE + mark_as_advanced( ${basename}_LIBRARY_RELEASE ${basename}_LIBRARY_DEBUG ) endmacro() diff --git a/Modules/UseEcos.cmake b/Modules/UseEcos.cmake index 028df8202..0c4fee4e1 100644 --- a/Modules/UseEcos.cmake +++ b/Modules/UseEcos.cmake @@ -132,10 +132,10 @@ macro(ECOS_ADJUST_DIRECTORY _target_FILES ) endmacro() # the default ecos config file name -# maybe in the future also out-of-source builds may be possible +# maybe in future also out-of-source builds may be possible set(ECOS_CONFIG_FILE ecos.ecc) -#creates the dependancy from all source files on the ecos target.ld, +#creates the dependency from all source files on the ecos target.ld, #adds the command for compiling ecos macro(ECOS_ADD_TARGET_LIB) # when building out-of-source, create the ecos/ subdir diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 043869519..c0fd07cbd 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -6,6 +6,10 @@ # add_jar(target_name # [SOURCES] source1 [source2 ...] [resource1 ...] # [INCLUDE_JARS jar1 [jar2 ...]] +# [ENTRY_POINT entry] +# [VERSION version] +# [OUTPUT_NAME name] +# [OUTPUT_DIR dir] # ) # # This command creates a <target_name>.jar. It compiles the given source files @@ -17,6 +21,9 @@ # listed as sources are ignored (as they have been since the first version of # this module). # +# The default OUTPUT_DIR can also be changed by setting the variable +# CMAKE_JAVA_TARGET_OUTPUT_DIR. +# # Additional instructions: # To add compile flags to the target you can set these flags with # the following variable: @@ -30,32 +37,30 @@ # # To use a different output name for the target you can set it with: # -# set(CMAKE_JAVA_TARGET_OUTPUT_NAME shibboleet.jar) -# add_jar(foobar foobar.java) +# add_jar(foobar foobar.java OUTPUT_NAME shibboleet.jar) # # To use a different output directory than CMAKE_CURRENT_BINARY_DIR # you can set it with: # -# set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin) +# add_jar(foobar foobar.java OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin) # -# To define an entry point in your jar you can set it with: +# To define an entry point in your jar you can set it with the ENTRY_POINT +# named argument: # -# set(CMAKE_JAVA_JAR_ENTRY_POINT com/examples/MyProject/Main) +# add_jar(example ENTRY_POINT com/examples/MyProject/Main) # # To add a VERSION to the target output name you can set it using -# CMAKE_JAVA_TARGET_VERSION. This will create a jar file with the name -# shibboleet-1.0.0.jar and will create a symlink shibboleet.jar +# the VERSION named argument to add_jar. This will create a jar file with the +# name shibboleet-1.0.0.jar and will create a symlink shibboleet.jar # pointing to the jar with the version information. # -# set(CMAKE_JAVA_TARGET_VERSION 1.2.0) -# add_jar(shibboleet shibbotleet.java) +# add_jar(shibboleet shibbotleet.java VERSION 1.2.0) # # If the target is a JNI library, utilize the following commands to # create a JNI symbolic link: # # set(CMAKE_JNI_TARGET TRUE) -# set(CMAKE_JAVA_TARGET_VERSION 1.2.0) -# add_jar(shibboleet shibbotleet.java) +# add_jar(shibboleet shibbotleet.java VERSION 1.2.0) # install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet) # install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR}) # @@ -185,8 +190,9 @@ # #============================================================================= +# Copyright 2013 OpenGamma Ltd. <graham@opengamma.com> # Copyright 2010-2011 Andreas schneider <asn@redhat.com> -# Copyright 2010 Ben Boeckel <ben.boeckel@kitware.com> +# Copyright 2010-2013 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. @@ -216,23 +222,50 @@ set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake) function(add_jar _TARGET_NAME) - cmake_parse_arguments(_add_jar "" "" "SOURCES;INCLUDE_JARS" ${ARGN}) + # In CMake < 2.8.12, add_jar used variables which were set prior to calling + # add_jar for customizing the behavior of add_jar. In order to be backwards + # compatible, check if any of those variables are set, and use them to + # initialize values of the named arguments. (Giving the corresponding named + # argument will override the value set here.) + # + # New features should use named arguments only. + if(DEFINED CMAKE_JAVA_TARGET_VERSION) + set(_add_jar_VERSION "${CMAKE_JAVA_TARGET_VERSION}") + endif() + if(DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR) + set(_add_jar_OUTPUT_DIR "${CMAKE_JAVA_TARGET_OUTPUT_DIR}") + endif() + if(DEFINED CMAKE_JAVA_TARGET_OUTPUT_NAME) + set(_add_jar_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}") + # reset + set(CMAKE_JAVA_TARGET_OUTPUT_NAME) + endif() + if(DEFINED CMAKE_JAVA_JAR_ENTRY_POINT) + set(_add_jar_ENTRY_POINT "${CMAKE_JAVA_JAR_ENTRY_POINT}") + endif() + + cmake_parse_arguments(_add_jar + "" + "VERSION;OUTPUT_DIR;OUTPUT_NAME;ENTRY_POINT" + "SOURCES;INCLUDE_JARS" + ${ARGN} + ) set(_JAVA_SOURCE_FILES ${_add_jar_SOURCES} ${_add_jar_UNPARSED_ARGUMENTS}) - if (NOT DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR) - set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) + if (NOT DEFINED _add_jar_OUTPUT_DIR) + set(_add_jar_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) endif() - if (CMAKE_JAVA_JAR_ENTRY_POINT) - set(_ENTRY_POINT_OPTION e) - set(_ENTRY_POINT_VALUE ${CMAKE_JAVA_JAR_ENTRY_POINT}) + if (_add_jar_ENTRY_POINT) + set(_ENTRY_POINT_OPTION e) + set(_ENTRY_POINT_VALUE ${_add_jar_ENTRY_POINT}) endif () if (LIBRARY_OUTPUT_PATH) set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH}) else () - set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR}) + set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${_add_jar_OUTPUT_DIR}) endif () set(CMAKE_JAVA_INCLUDE_PATH @@ -242,7 +275,7 @@ function(add_jar _TARGET_NAME) ${CMAKE_JAVA_LIBRARY_OUTPUT_PATH} ) - if (WIN32 AND NOT CYGWIN) + if (WIN32 AND NOT CYGWIN AND CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") set(CMAKE_JAVA_INCLUDE_FLAG_SEP ";") else () set(CMAKE_JAVA_INCLUDE_FLAG_SEP ":") @@ -252,20 +285,18 @@ function(add_jar _TARGET_NAME) set(CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_PATH_FINAL}${CMAKE_JAVA_INCLUDE_FLAG_SEP}${JAVA_INCLUDE_DIR}") endforeach() - set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${CMAKE_JAVA_TARGET_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir") + set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${_add_jar_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir") set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}.jar") - if (CMAKE_JAVA_TARGET_OUTPUT_NAME AND CMAKE_JAVA_TARGET_VERSION) - set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar") - set(_JAVA_TARGET_OUTPUT_LINK "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar") - elseif (CMAKE_JAVA_TARGET_VERSION) - set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar") + if (_add_jar_OUTPUT_NAME AND _add_jar_VERSION) + set(_JAVA_TARGET_OUTPUT_NAME "${_add_jar_OUTPUT_NAME}-${_add_jar_VERSION}.jar") + set(_JAVA_TARGET_OUTPUT_LINK "${_add_jar_OUTPUT_NAME}.jar") + elseif (_add_jar_VERSION) + set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}-${_add_jar_VERSION}.jar") set(_JAVA_TARGET_OUTPUT_LINK "${_TARGET_NAME}.jar") - elseif (CMAKE_JAVA_TARGET_OUTPUT_NAME) - set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar") + elseif (_add_jar_OUTPUT_NAME) + set(_JAVA_TARGET_OUTPUT_NAME "${_add_jar_OUTPUT_NAME}.jar") endif () - # reset - set(CMAKE_JAVA_TARGET_OUTPUT_NAME) set(_JAVA_CLASS_FILES) set(_JAVA_COMPILE_FILES) @@ -279,7 +310,7 @@ function(add_jar _TARGET_NAME) get_filename_component(_JAVA_FULL ${_JAVA_SOURCE_FILE} ABSOLUTE) if (_JAVA_EXT MATCHES ".java") - file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR} ${_JAVA_FULL}) + file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${_add_jar_OUTPUT_DIR} ${_JAVA_FULL}) file(RELATIVE_PATH _JAVA_REL_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${_JAVA_FULL}) string(LENGTH ${_JAVA_REL_BINARY_PATH} _BIN_LEN) string(LENGTH ${_JAVA_REL_SOURCE_PATH} _SRC_LEN) @@ -337,6 +368,11 @@ function(add_jar _TARGET_NAME) endif() if (_JAVA_COMPILE_FILES) + # Create the list of files to compile. + set(_JAVA_SOURCES_FILE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_sources) + string(REPLACE ";" "\"\n\"" _JAVA_COMPILE_STRING "\"${_JAVA_COMPILE_FILES}\"") + file(WRITE ${_JAVA_SOURCES_FILE} ${_JAVA_COMPILE_STRING}) + # Compile the java files and create a list of class files add_custom_command( # NOTE: this command generates an artificial dependency file @@ -345,7 +381,7 @@ function(add_jar _TARGET_NAME) ${CMAKE_JAVA_COMPILE_FLAGS} -classpath "${CMAKE_JAVA_INCLUDE_PATH_FINAL}" -d ${CMAKE_JAVA_CLASS_OUTPUT_PATH} - ${_JAVA_COMPILE_FILES} + @${_JAVA_SOURCES_FILE} COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME} DEPENDS ${_JAVA_COMPILE_FILES} ${_JAVA_COMPILE_DEPENDS} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} @@ -364,7 +400,7 @@ function(add_jar _TARGET_NAME) # create the jar file set(_JAVA_JAR_OUTPUT_PATH - ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME}) + ${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME}) if (CMAKE_JNI_TARGET) add_custom_command( OUTPUT ${_JAVA_JAR_OUTPUT_PATH} @@ -372,12 +408,12 @@ function(add_jar _TARGET_NAME) -cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE} ${_JAVA_RESOURCE_FILES} @java_class_filelist COMMAND ${CMAKE_COMMAND} - -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR} + -D_JAVA_TARGET_DIR=${_add_jar_OUTPUT_DIR} -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME} -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK} -P ${_JAVA_SYMLINK_SCRIPT} COMMAND ${CMAKE_COMMAND} - -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR} + -D_JAVA_TARGET_DIR=${_add_jar_OUTPUT_DIR} -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_JAR_OUTPUT_PATH} -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK} -P ${_JAVA_SYMLINK_SCRIPT} @@ -392,7 +428,7 @@ function(add_jar _TARGET_NAME) -cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE} ${_JAVA_RESOURCE_FILES} @java_class_filelist COMMAND ${CMAKE_COMMAND} - -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR} + -D_JAVA_TARGET_DIR=${_add_jar_OUTPUT_DIR} -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME} -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK} -P ${_JAVA_SYMLINK_SCRIPT} @@ -420,7 +456,7 @@ function(add_jar _TARGET_NAME) PROPERTY INSTALL_FILES ${_JAVA_JAR_OUTPUT_PATH} - ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} + ${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} ) if (CMAKE_JNI_TARGET) @@ -429,7 +465,7 @@ function(add_jar _TARGET_NAME) ${_TARGET_NAME} PROPERTY JNI_SYMLINK - ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} + ${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} ) endif () endif () diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index f0519fe7c..8412e3e86 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -11,7 +11,11 @@ #============================================================================= include(CheckIncludeFile) # Check if we can build support for ELF parsing. -CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H) +if(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD") + CHECK_INCLUDE_FILES("stdint.h;elf_abi.h" HAVE_ELF_H) +else() + CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H) +endif() if(HAVE_ELF_H) set(CMAKE_USE_ELF_PARSER 1) else() @@ -113,7 +117,8 @@ endif() set(SRCS cmStandardIncludes.cxx cmArchiveWrite.cxx - cmBootstrapCommands.cxx + cmBootstrapCommands1.cxx + cmBootstrapCommands2.cxx cmCacheManager.cxx cmCacheManager.h cmCommands.cxx @@ -359,6 +364,10 @@ if (WIN32) cmLocalVisualStudio7Generator.h cmLocalVisualStudioGenerator.cxx cmLocalVisualStudioGenerator.h + cmVisualStudioSlnData.h + cmVisualStudioSlnData.cxx + cmVisualStudioSlnParser.h + cmVisualStudioSlnParser.cxx cmVisualStudioWCEPlatformParser.h cmVisualStudioWCEPlatformParser.cxx cmWin32ProcessExecution.cxx @@ -385,7 +394,7 @@ if(WIN32 AND NOT CYGWIN AND NOT BORLAND) set_source_files_properties(cmcldeps.cxx PROPERTIES COMPILE_DEFINITIONS _WIN32_WINNT=0x0501) add_executable(cmcldeps cmcldeps.cxx) target_link_libraries(cmcldeps CMakeLib) - install_targets(/bin cmcldeps) + install(TARGETS cmcldeps DESTINATION bin) endif() # create a library used by the command line and the GUI @@ -539,12 +548,13 @@ endif() add_executable(cmake cmakemain.cxx) target_link_libraries(cmake CMakeLib) -# Build special executable for running programs on Windows 98 +# Build special executable for running programs on Windows 98. +# Included on any Windows (unconditional packaging required!). if(WIN32) if(NOT UNIX) add_executable(cmw9xcom cmw9xcom.cxx) target_link_libraries(cmw9xcom CMakeLib) - install_targets(/bin cmw9xcom) + install(TARGETS cmw9xcom DESTINATION bin) endif() endif() @@ -570,11 +580,9 @@ endif() include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL) include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL) -install_targets(/bin cmake) -install_targets(/bin ctest) -install_targets(/bin cpack) +install(TARGETS cmake ctest cpack DESTINATION bin) if(APPLE) - install_targets(/bin cmakexbuild) + install(TARGETS cmakexbuild DESTINATION bin) endif() -install_files(${CMAKE_DATA_DIR}/include cmCPluginAPI.h) +install(FILES cmCPluginAPI.h DESTINATION ${CMAKE_DATA_DIR}/include) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a8b890775..fd315ce6c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,6 +1,6 @@ # CMake version number components. set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) -set(CMake_VERSION_PATCH 11) +set(CMake_VERSION_PATCH 12) set(CMake_VERSION_TWEAK 2) #set(CMake_VERSION_RC 0) diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index e8b0ea971..cc9dec7b8 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -100,6 +100,11 @@ bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles) command << " -nologo"; command << " -out " << QuotePath(packageFileNames.at(0)); command << " -ext WixUIExtension"; + const char* const cultures = GetOption("CPACK_WIX_CULTURES"); + if(cultures) + { + command << " -cultures:" << cultures; + } command << " " << objectFiles; return RunWiXCommand(command.str()); @@ -224,6 +229,9 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON"); CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER"); CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG"); + SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER", + GetOption("CPACK_PACKAGE_NAME")); + CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER"); return true; } @@ -339,25 +347,114 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() featureDefinitions.BeginElement("FeatureRef"); featureDefinitions.AddAttribute("Id", "ProductFeature"); + const char *cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); + std::vector<std::string> cpackPkgExecutables; + std::string regKey; + if ( cpackPackageExecutables ) + { + cmSystemTools::ExpandListArgument(cpackPackageExecutables, + cpackPkgExecutables); + if ( cpackPkgExecutables.size() % 2 != 0 ) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and " + "<icon name>." << std::endl); + cpackPkgExecutables.clear(); + } + + const char *cpackVendor = GetOption("CPACK_PACKAGE_VENDOR"); + const char *cpackPkgName = GetOption("CPACK_PACKAGE_NAME"); + if (!cpackVendor || !cpackPkgName) + { + cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_PACKAGE_VENDOR and " + "CPACK_PACKAGE_NAME must be defined for shortcut creation" << std::endl); + cpackPkgExecutables.clear(); + } + else + { + regKey = std::string("Software/") + cpackVendor + "/" + cpackPkgName; + } + } + + std::vector<std::string> dirIdExecutables; AddDirectoryAndFileDefinitons( toplevel, "INSTALL_ROOT", directoryDefinitions, fileDefinitions, featureDefinitions, - directoryCounter, fileCounter); + directoryCounter, fileCounter, cpackPkgExecutables, dirIdExecutables); - featureDefinitions.EndElement(); - featureDefinitions.EndElement(); - fileDefinitions.EndElement(); + directoryDefinitions.EndElement(); + directoryDefinitions.EndElement(); - for(size_t i = 1; i < install_root.size(); ++i) + if (dirIdExecutables.size() > 0 && dirIdExecutables.size() % 3 == 0) { - directoryDefinitions.EndElement(); - } + fileDefinitions.BeginElement("DirectoryRef"); + fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + fileDefinitions.BeginElement("Component"); + fileDefinitions.AddAttribute("Id", "SHORTCUT"); + fileDefinitions.AddAttribute("Guid", "*"); - directoryDefinitions.EndElement(); - directoryDefinitions.EndElement(); + std::vector<std::string>::iterator it; + for ( it = dirIdExecutables.begin() ; + it != dirIdExecutables.end(); + ++it) + { + std::string fileName = *it++; + std::string iconName = *it++; + std::string directoryId = *it; + + fileDefinitions.BeginElement("Shortcut"); + std::string shortcutName = fileName; // the iconName is mor likely to contain blanks early on + std::string::size_type const dotPos = shortcutName.find('.'); + if(std::string::npos == dotPos) + { shortcutName = shortcutName.substr(0, dotPos); } + fileDefinitions.AddAttribute("Id", "SHORTCUT_" + shortcutName); + fileDefinitions.AddAttribute("Name", iconName); + std::string target = "[" + directoryId + "]" + fileName; + fileDefinitions.AddAttribute("Target", target); + fileDefinitions.AddAttribute("WorkingDirectory", directoryId); + fileDefinitions.EndElement(); + } + fileDefinitions.BeginElement("Shortcut"); + fileDefinitions.AddAttribute("Id", "UNINSTALL"); + std::string pkgName = GetOption("CPACK_PACKAGE_NAME"); + fileDefinitions.AddAttribute("Name", "Uninstall " + pkgName); + fileDefinitions.AddAttribute("Description", "Uninstalls " + pkgName); + fileDefinitions.AddAttribute("Target", "[SystemFolder]msiexec.exe"); + fileDefinitions.AddAttribute("Arguments", "/x [ProductCode]"); + fileDefinitions.EndElement(); + fileDefinitions.BeginElement("RemoveFolder"); + fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + fileDefinitions.AddAttribute("On", "uninstall"); + fileDefinitions.EndElement(); + fileDefinitions.BeginElement("RegistryValue"); + fileDefinitions.AddAttribute("Root", "HKCU"); + fileDefinitions.AddAttribute("Key", regKey); + fileDefinitions.AddAttribute("Name", "installed"); + fileDefinitions.AddAttribute("Type", "integer"); + fileDefinitions.AddAttribute("Value", "1"); + fileDefinitions.AddAttribute("KeyPath", "yes"); + + featureDefinitions.BeginElement("ComponentRef"); + featureDefinitions.AddAttribute("Id", "SHORTCUT"); + featureDefinitions.EndElement(); + directoryDefinitions.BeginElement("Directory"); + directoryDefinitions.AddAttribute("Id", "ProgramMenuFolder"); + directoryDefinitions.BeginElement("Directory"); + directoryDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER"); + const char *startMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); + directoryDefinitions.AddAttribute("Name", startMenuFolder); + } + + featureDefinitions.EndElement(); + featureDefinitions.EndElement(); + fileDefinitions.EndElement(); directoryDefinitions.EndElement(); std::string wixTemplate = FindTemplate("WIX.template.in"); + if(GetOption("CPACK_WIX_TEMPLATE") != 0) + { + wixTemplate = GetOption("CPACK_WIX_TEMPLATE"); + } if(wixTemplate.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -435,7 +532,9 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( cmWIXSourceWriter& fileDefinitions, cmWIXSourceWriter& featureDefinitions, size_t& directoryCounter, - size_t& fileCounter) + size_t& fileCounter, + const std::vector<std::string>& pkgExecutables, + std::vector<std::string>& dirIdExecutables) { cmsys::Directory dir; dir.Load(topdir.c_str()); @@ -467,8 +566,9 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( fileDefinitions, featureDefinitions, directoryCounter, - fileCounter); - + fileCounter, + pkgExecutables, + dirIdExecutables); directoryDefinitions.EndElement(); } else @@ -499,6 +599,23 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( featureDefinitions.BeginElement("ComponentRef"); featureDefinitions.AddAttribute("Id", componentId); featureDefinitions.EndElement(); + + std::vector<std::string>::const_iterator it; + for (it = pkgExecutables.begin() ; + it != pkgExecutables.end() ; + ++it) + { + std::string execName = *it++; + std::string iconName = *it; + + if (cmSystemTools::LowerCase(fileName) == + cmSystemTools::LowerCase(execName) + ".exe") + { + dirIdExecutables.push_back(fileName); + dirIdExecutables.push_back(iconName); + dirIdExecutables.push_back(directoryId); + } + } } } } diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index 0e95d70f6..aaccf9d46 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -83,7 +83,11 @@ private: cmWIXSourceWriter& fileDefinitions, cmWIXSourceWriter& featureDefinitions, size_t& directoryCounter, - size_t& fileCounter); + size_t& fileCounter, + const std::vector<std::string>& pkgExecutables, + std::vector<std::string>& dirIdExecutables + ); + bool RequireOption(const std::string& name, std::string& value) const; diff --git a/Source/CPack/cmCPackDocumentVariables.cxx b/Source/CPack/cmCPackDocumentVariables.cxx index 6a841fa8d..8b16ae985 100644 --- a/Source/CPack/cmCPackDocumentVariables.cxx +++ b/Source/CPack/cmCPackDocumentVariables.cxx @@ -28,7 +28,7 @@ void cmCPackDocumentVariables::DefineVariables(cmake* cm) " the so-called top level directory. The purpose of" " is to include (set to 1 or ON or TRUE) the top level directory" " in the package or not (set to 0 or OFF or FALSE).\n" - "Each CPack generator as a built-in default value for this" + "Each CPack generator has a built-in default value for this" " variable. E.g. Archive generators (ZIP, TGZ, ...) includes" " the top level whereas RPM or DEB don't. The user may override" " the default value by setting this variable.\n" @@ -60,7 +60,7 @@ void cmCPackDocumentVariables::DefineVariables(cmake* cm) "It is usually invoked like this:\n" " make DESTDIR=/home/john install\n" "which will install the concerned software using the" - " installation prefix, e.g. \"/usr/local\" pre-pended with " + " installation prefix, e.g. \"/usr/local\" prepended with " "the DESTDIR value which finally gives \"/home/john/usr/local\"." " When preparing a package, CPack first installs the items to be " "packaged in a local (to the build tree) directory by using the " diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 7cc152269..3c685bd9d 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -638,7 +638,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( = this->MakefileMap->GetDefinition("CMAKE_MAKE_PROGRAM"); std::string buildCommand = globalGenerator->GenerateBuildCommand(cmakeMakeProgram, - installProjectName.c_str(), 0, + installProjectName.c_str(), 0, 0, globalGenerator->GetPreinstallTargetName(), buildConfig, false, false); cmCPackLogger(cmCPackLog::LOG_DEBUG, diff --git a/Source/CTest/cmCTestBatchTestHandler.cxx b/Source/CTest/cmCTestBatchTestHandler.cxx index a22c7be41..934481b88 100644 --- a/Source/CTest/cmCTestBatchTestHandler.cxx +++ b/Source/CTest/cmCTestBatchTestHandler.cxx @@ -89,7 +89,7 @@ void cmCTestBatchTestHandler::WriteTestCommand(int test, std::fstream& fout) command = cmSystemTools::ConvertToOutputPath(command.c_str()); //Prepends memcheck args to our command string if this is a memcheck - this->TestHandler->GenerateTestCommand(processArgs); + this->TestHandler->GenerateTestCommand(processArgs, test); processArgs.push_back(command); for(std::vector<std::string>::iterator arg = processArgs.begin(); diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index f4d38cef1..1f63185c1 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -130,10 +130,11 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() cmakeBuildConfiguration = config; } + std::string dir = this->CTest->GetCTestConfiguration("BuildDirectory"); std::string buildCommand = this->GlobalGenerator-> GenerateBuildCommand(cmakeMakeProgram, - cmakeProjectName, + cmakeProjectName, dir.c_str(), cmakeBuildAdditionalFlags, cmakeBuildTarget, cmakeBuildConfiguration, true, false); cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index d6d39a98f..db33cb68e 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -31,32 +31,6 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() cmSystemTools::ExpandListArgument(this->Values[ctc_OPTIONS], options); } - if ( this->Values[ct_BUILD] ) - { - this->CTest->SetCTestConfiguration("BuildDirectory", - cmSystemTools::CollapseFullPath( - this->Values[ct_BUILD]).c_str()); - } - else - { - this->CTest->SetCTestConfiguration("BuildDirectory", - cmSystemTools::CollapseFullPath( - this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY")).c_str()); - } - - if ( this->Values[ct_SOURCE] ) - { - this->CTest->SetCTestConfiguration("SourceDirectory", - cmSystemTools::CollapseFullPath( - this->Values[ct_SOURCE]).c_str()); - } - else - { - this->CTest->SetCTestConfiguration("SourceDirectory", - cmSystemTools::CollapseFullPath( - this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY")).c_str()); - } - if ( this->CTest->GetCTestConfiguration("BuildDirectory").empty() ) { this->SetError("Build directory not specified. Either use BUILD " diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 453e32ce2..2e2feb047 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -70,19 +70,6 @@ bool cmCTestHandlerCommand this->CTest->SetConfigType(ctestConfigType); } - cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;); - cmCTestGenericHandler* handler = this->InitializeHandler(); - if ( !handler ) - { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Cannot instantiate test handler " << this->GetName() - << std::endl); - return false; - } - - handler->SetAppendXML(this->AppendXML); - - handler->PopulateCustomVectors(this->Makefile); if ( this->Values[ct_BUILD] ) { this->CTest->SetCTestConfiguration("BuildDirectory", @@ -119,6 +106,20 @@ bool cmCTestHandlerCommand cmSystemTools::CollapseFullPath( this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY")).c_str()); } + + cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;); + cmCTestGenericHandler* handler = this->InitializeHandler(); + if ( !handler ) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot instantiate test handler " << this->GetName() + << std::endl); + return false; + } + + handler->SetAppendXML(this->AppendXML); + + handler->PopulateCustomVectors(this->Makefile); if ( this->Values[ct_SUBMIT_INDEX] ) { if(!this->CTest->GetDropSiteCDash() && this->CTest->GetDartVersion() <= 1) diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 80218ad38..3ae2ac6a7 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -43,8 +43,7 @@ static CatToErrorType cmCTestMemCheckBoundsChecker[] = { {0,0} }; -// parse the xml file storing the installed version of Xcode on -// the machine +// parse the xml file containing the results of last BoundsChecker run class cmBoundsCheckerParser : public cmXMLParser { public: @@ -201,6 +200,7 @@ void cmCTestMemCheckHandler::Initialize() this->CustomMaximumPassedTestOutputSize = 0; this->CustomMaximumFailedTestOutputSize = 0; this->MemoryTester = ""; + this->MemoryTesterDynamicOptions.clear(); this->MemoryTesterOptions.clear(); this->MemoryTesterStyle = UNKNOWN; this->MemoryTesterOutputFile = ""; @@ -243,12 +243,28 @@ int cmCTestMemCheckHandler::PostProcessHandler() //---------------------------------------------------------------------- void cmCTestMemCheckHandler::GenerateTestCommand( - std::vector<std::string>& args) + std::vector<std::string>& args, int test) { std::vector<cmStdString>::size_type pp; - std::string memcheckcommand = ""; - memcheckcommand + cmStdString index; + cmOStringStream stream; + std::string memcheckcommand = cmSystemTools::ConvertToOutputPath(this->MemoryTester.c_str()); + stream << test; + index = stream.str(); + for ( pp = 0; pp < this->MemoryTesterDynamicOptions.size(); pp ++ ) + { + cmStdString arg = this->MemoryTesterDynamicOptions[pp]; + cmStdString::size_type pos = arg.find("??"); + if (pos != cmStdString::npos) + { + arg.replace(pos, 2, index); + } + args.push_back(arg); + memcheckcommand += " \""; + memcheckcommand += arg; + memcheckcommand += "\""; + } for ( pp = 0; pp < this->MemoryTesterOptions.size(); pp ++ ) { args.push_back(this->MemoryTesterOptions[pp]); @@ -461,13 +477,6 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() return false; } - if ( this->MemoryTester[0] == '\"' && - this->MemoryTester[this->MemoryTester.size()-1] == '\"' ) - { - this->MemoryTester - = this->MemoryTester.substr(1, this->MemoryTester.size()-2); - } - // Setup the options std::string memoryTesterOptions; if ( this->CTest->GetCTestConfiguration( @@ -486,18 +495,19 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() = cmSystemTools::ParseArguments(memoryTesterOptions.c_str()); this->MemoryTesterOutputFile - = this->CTest->GetBinaryDir() + "/Testing/Temporary/MemoryChecker.log"; + = this->CTest->GetBinaryDir() + + "/Testing/Temporary/MemoryChecker.??.log"; switch ( this->MemoryTesterStyle ) { case cmCTestMemCheckHandler::VALGRIND: + { if ( this->MemoryTesterOptions.empty() ) { this->MemoryTesterOptions.push_back("-q"); this->MemoryTesterOptions.push_back("--tool=memcheck"); this->MemoryTesterOptions.push_back("--leak-check=yes"); this->MemoryTesterOptions.push_back("--show-reachable=yes"); - this->MemoryTesterOptions.push_back("--workaround-gcc296-bugs=yes"); this->MemoryTesterOptions.push_back("--num-callers=50"); } if ( this->CTest->GetCTestConfiguration( @@ -516,7 +526,11 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile"); this->MemoryTesterOptions.push_back(suppressions); } + std::string outputFile = "--log-file=" + + this->MemoryTesterOutputFile; + this->MemoryTesterDynamicOptions.push_back(outputFile); break; + } case cmCTestMemCheckHandler::PURIFY: { std::string outputFile; @@ -542,19 +556,19 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() outputFile = "-log-file="; #endif outputFile += this->MemoryTesterOutputFile; - this->MemoryTesterOptions.push_back(outputFile); + this->MemoryTesterDynamicOptions.push_back(outputFile); break; } case cmCTestMemCheckHandler::BOUNDS_CHECKER: { this->BoundsCheckerXMLFile = this->MemoryTesterOutputFile; std::string dpbdFile = this->CTest->GetBinaryDir() - + "/Testing/Temporary/MemoryChecker.DPbd"; + + "/Testing/Temporary/MemoryChecker.??.DPbd"; this->BoundsCheckerDPBDFile = dpbdFile; - this->MemoryTesterOptions.push_back("/B"); - this->MemoryTesterOptions.push_back(dpbdFile); - this->MemoryTesterOptions.push_back("/X"); - this->MemoryTesterOptions.push_back(this->MemoryTesterOutputFile); + this->MemoryTesterDynamicOptions.push_back("/B"); + this->MemoryTesterDynamicOptions.push_back(dpbdFile); + this->MemoryTesterDynamicOptions.push_back("/X"); + this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile); this->MemoryTesterOptions.push_back("/M"); break; } @@ -902,25 +916,23 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( // This method puts the bounds checker output file into the output // for the test void -cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res) +cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res, + int test) { cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "PostProcessBoundsCheckerTest for : " << res.Name.c_str() << std::endl); - if ( !cmSystemTools::FileExists(this->MemoryTesterOutputFile.c_str()) ) + cmStdString ofile = testOutputFileName(test); + if ( ofile.empty() ) { - std::string log = "Cannot find memory tester output file: " - + this->MemoryTesterOutputFile; - cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl); return; } // put a scope around this to close ifs so the file can be removed { - std::ifstream ifs(this->MemoryTesterOutputFile.c_str()); + std::ifstream ifs(ofile.c_str()); if ( !ifs ) { - std::string log = "Cannot read memory tester output file: " - + this->MemoryTesterOutputFile; + std::string log = "Cannot read memory tester output file: " + ofile; cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl); return; } @@ -943,23 +955,39 @@ cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res) } void -cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res) +cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res, + int test) { cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "PostProcessPurifyTest for : " << res.Name.c_str() << std::endl); - if ( !cmSystemTools::FileExists(this->MemoryTesterOutputFile.c_str()) ) + appendMemTesterOutput(res, test); +} + +void +cmCTestMemCheckHandler::PostProcessValgrindTest(cmCTestTestResult& res, + int test) +{ + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "PostProcessValgrindTest for : " + << res.Name.c_str() << std::endl); + appendMemTesterOutput(res, test); +} + +void +cmCTestMemCheckHandler::appendMemTesterOutput(cmCTestTestResult& res, + int test) +{ + cmStdString ofile = testOutputFileName(test); + + if ( ofile.empty() ) { - std::string log = "Cannot find memory tester output file: " - + this->MemoryTesterOutputFile; - cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl); return; } - std::ifstream ifs(this->MemoryTesterOutputFile.c_str()); + std::ifstream ifs(ofile.c_str()); if ( !ifs ) { - std::string log = "Cannot read memory tester output file: " - + this->MemoryTesterOutputFile; + std::string log = "Cannot read memory tester output file: " + ofile; cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl); return; } @@ -970,3 +998,25 @@ cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res) res.Output += "\n"; } } + +cmStdString +cmCTestMemCheckHandler::testOutputFileName(int test) +{ + cmStdString index; + cmOStringStream stream; + stream << test; + index = stream.str(); + cmStdString ofile = this->MemoryTesterOutputFile; + cmStdString::size_type pos = ofile.find("??"); + ofile.replace(pos, 2, index); + + if ( !cmSystemTools::FileExists(ofile.c_str()) ) + { + std::string log = "Cannot find memory tester output file: " + + ofile; + cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl); + ofile = ""; + } + + return ofile; +} diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index 1e81c893b..040d2e092 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -37,7 +37,7 @@ public: protected: virtual int PreProcessHandler(); virtual int PostProcessHandler(); - virtual void GenerateTestCommand(std::vector<std::string>& args); + virtual void GenerateTestCommand(std::vector<std::string>& args, int test); private: @@ -89,6 +89,7 @@ private: std::string BoundsCheckerDPBDFile; std::string BoundsCheckerXMLFile; std::string MemoryTester; + std::vector<cmStdString> MemoryTesterDynamicOptions; std::vector<cmStdString> MemoryTesterOptions; int MemoryTesterStyle; std::string MemoryTesterOutputFile; @@ -117,8 +118,16 @@ private: bool ProcessMemCheckBoundsCheckerOutput(const std::string& str, std::string& log, int* results); - void PostProcessPurifyTest(cmCTestTestResult& res); - void PostProcessBoundsCheckerTest(cmCTestTestResult& res); + void PostProcessPurifyTest(cmCTestTestResult& res, int test); + void PostProcessBoundsCheckerTest(cmCTestTestResult& res, int test); + void PostProcessValgrindTest(cmCTestTestResult& res, int test); + + ///! append MemoryTesterOutputFile to the test log + void appendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res, + int test); + + ///! generate the output filename for the given test index + cmStdString testOutputFileName(int test); }; #endif diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 5eabf3fbe..0e2fa41b9 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -166,6 +166,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) { found = true; reason = "Required regular expression found."; + break; } } if ( !found ) @@ -196,6 +197,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) reason += passIt->second; reason += "]"; forceFail = true; + break; } } } @@ -384,13 +386,19 @@ void cmCTestRunTest::MemCheckPostProcess() << this->TestResult.Name.c_str() << std::endl); cmCTestMemCheckHandler * handler = static_cast<cmCTestMemCheckHandler*> (this->TestHandler); - if(handler->MemoryTesterStyle == cmCTestMemCheckHandler::BOUNDS_CHECKER) - { - handler->PostProcessBoundsCheckerTest(this->TestResult); - } - else if(handler->MemoryTesterStyle == cmCTestMemCheckHandler::PURIFY) + switch ( handler->MemoryTesterStyle ) { - handler->PostProcessPurifyTest(this->TestResult); + case cmCTestMemCheckHandler::VALGRIND: + handler->PostProcessValgrindTest(this->TestResult, this->Index); + break; + case cmCTestMemCheckHandler::PURIFY: + handler->PostProcessPurifyTest(this->TestResult, this->Index); + break; + case cmCTestMemCheckHandler::BOUNDS_CHECKER: + handler->PostProcessBoundsCheckerTest(this->TestResult, this->Index); + break; + default: + break; } } @@ -516,7 +524,7 @@ void cmCTestRunTest::ComputeArguments() = cmSystemTools::ConvertToOutputPath(this->ActualCommand.c_str()); //Prepends memcheck args to our command string - this->TestHandler->GenerateTestCommand(this->Arguments); + this->TestHandler->GenerateTestCommand(this->Arguments, this->Index); for(std::vector<std::string>::iterator i = this->Arguments.begin(); i != this->Arguments.end(); ++i) { diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 142bb4613..941d34877 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -120,7 +120,7 @@ static size_t cmCTestSubmitHandlerWriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) { - register int realsize = (int)(size * nmemb); + int realsize = (int)(size * nmemb); cmCTestSubmitHandlerVectorOfChar *vec = static_cast<cmCTestSubmitHandlerVectorOfChar*>(data); diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index e7491bba3..497774d1b 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -82,7 +82,6 @@ bool cmCTestSubdirCommand std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); for ( it = args.begin(); it != args.end(); ++ it ) { - cmSystemTools::ChangeDirectory(cwd.c_str()); std::string fname; if(cmSystemTools::FileIsFullPath(it->c_str())) @@ -116,7 +115,6 @@ bool cmCTestSubdirCommand else { // No CTestTestfile? Who cares... - cmSystemTools::ChangeDirectory(cwd.c_str()); continue; } fname += "/"; @@ -133,6 +131,7 @@ bool cmCTestSubdirCommand return false; } } + cmSystemTools::ChangeDirectory(cwd.c_str()); return true; } @@ -1108,7 +1107,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed, } //---------------------------------------------------------------------- -void cmCTestTestHandler::GenerateTestCommand(std::vector<std::string>&) +void cmCTestTestHandler::GenerateTestCommand(std::vector<std::string>&, int) { } @@ -1303,10 +1302,9 @@ int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec) for ( it = vec.begin(); it != vec.end(); ++it ) { int retVal = 0; - std::string cmd = cmSystemTools::ConvertToOutputPath(it->c_str()); - cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " << cmd + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " << *it << std::endl); - if ( !cmSystemTools::RunSingleCommand(cmd.c_str(), 0, &retVal, 0, + if ( !cmSystemTools::RunSingleCommand(it->c_str(), 0, &retVal, 0, cmSystemTools::OUTPUT_MERGE /*this->Verbose*/) || retVal != 0 ) { @@ -1363,7 +1361,7 @@ void cmCTestTestHandler tempPath += filename; attempted.push_back(tempPath); attemptedConfigs.push_back(ctest->GetConfigType()); - // If the file is an OSX bundle then the configtyp + // If the file is an OSX bundle then the configtype // will be at the start of the path tempPath = ctest->GetConfigType(); tempPath += "/"; @@ -1374,7 +1372,7 @@ void cmCTestTestHandler } else { - // no config specified to try some options + // no config specified - try some options... tempPath = filepath; tempPath += "Release/"; tempPath += filename; diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 8e59e5915..93b793b20 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -153,7 +153,7 @@ protected: // compute a final test list virtual int PreProcessHandler(); virtual int PostProcessHandler(); - virtual void GenerateTestCommand(std::vector<std::string>& args); + virtual void GenerateTestCommand(std::vector<std::string>& args, int test); int ExecuteCommands(std::vector<cmStdString>& vec); void WriteTestResultHeader(std::ostream& os, cmCTestTestResult* result); diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx index 5dfcfe50a..6b4adb4bd 100644 --- a/Source/CTest/cmParseGTMCoverage.cxx +++ b/Source/CTest/cmParseGTMCoverage.cxx @@ -98,7 +98,7 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file) bool found = this->FindMumpsFile(routine, filepath); if(found) { - int lineoffset; + int lineoffset = 0; if(this->FindFunctionInMumpsFile(filepath, function, lineoffset)) @@ -106,8 +106,8 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file) cmCTestCoverageHandlerContainer::SingleFileCoverageVector& coverageVector = this->Coverage.TotalCoverage[filepath]; coverageVector[lineoffset + linenumber] += count; + lastoffset = lineoffset; } - lastoffset = lineoffset; } else { diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 000bc8503..167b992c9 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -175,6 +175,14 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout) // Record exit information. this->ExitValue = cmsysProcess_GetExitValue(this->Process); this->TotalTime = cmSystemTools::GetTime() - this->StartTime; + // Because of a processor clock scew the runtime may become slightly + // negative. If someone changed the system clock while the process was + // running this may be even more. Make sure not to report a negative + // duration here. + if (this->TotalTime <= 0.0) + { + this->TotalTime = 0.0; + } // std::cerr << "Time to run: " << this->TotalTime << "\n"; return cmsysProcess_Pipe_None; } diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt index 96e28b491..5efc2fb1a 100644 --- a/Source/CursesDialog/CMakeLists.txt +++ b/Source/CursesDialog/CMakeLists.txt @@ -34,4 +34,4 @@ add_executable(ccmake ${CURSES_SRCS} ) target_link_libraries(ccmake CMakeLib) target_link_libraries(ccmake cmForm) -install_targets(/bin ccmake) +install(TARGETS ccmake DESTINATION bin) diff --git a/Source/CursesDialog/form/frm_driver.c b/Source/CursesDialog/form/frm_driver.c index f234722f3..b9611bf10 100644 --- a/Source/CursesDialog/form/frm_driver.c +++ b/Source/CursesDialog/form/frm_driver.c @@ -176,7 +176,7 @@ static int FE_Delete_Previous(FORM *); #define Address_Of_Current_Position_In_Buffer(form) \ Address_Of_Current_Position_In_Nth_Buffer(form,0) -/* Logic to decide wether or not a field is actually a field with +/* Logic to decide whether or not a field is actually a field with vertical or horizontal scrolling */ #define Is_Scroll_Field(field) \ (((field)->drows > (field)->rows) || \ @@ -2100,7 +2100,7 @@ static int Insert_String(FORM *form, int row, char *txt, int len) | the wrapping. | | Return Values : E_OK - no wrapping required or wrapping -| was successfull +| was successful | E_REQUEST_DENIED - | E_SYSTEM_ERROR - some system error +--------------------------------------------------------------------------*/ @@ -3825,7 +3825,7 @@ int set_field_buffer(FIELD * field, int buffer, const char * value) (int)(1 + (vlen-len)/((field->rows+field->nrow)*field->cols)))) RETURN(E_SYSTEM_ERROR); - /* in this case we also have to check, wether or not the remaining + /* in this case we also have to check, whether or not the remaining characters in value are also printable for buffer 0. */ if (buffer==0) { diff --git a/Source/CursesDialog/form/fty_enum.c b/Source/CursesDialog/form/fty_enum.c index 8fc4cd7b6..59058a98c 100644 --- a/Source/CursesDialog/form/fty_enum.c +++ b/Source/CursesDialog/form/fty_enum.c @@ -101,7 +101,7 @@ static void Free_Enum_Type(void * argp) | const unsigned char * buf, | bool ccase ) | -| Description : Check wether or not the text in 'buf' matches the +| Description : Check whether or not the text in 'buf' matches the | text in 's', at least partial. | | Return Values : NOMATCH - buffer doesn't match diff --git a/Source/CursesDialog/form/fty_ipv4.c b/Source/CursesDialog/form/fty_ipv4.c index 4ac8a50ec..c855af655 100644 --- a/Source/CursesDialog/form/fty_ipv4.c +++ b/Source/CursesDialog/form/fty_ipv4.c @@ -30,7 +30,7 @@ static bool Check_IPV4_Field(FIELD * field, const void * argp) { char *bp = field_buffer(field,0); int num = 0, len; - unsigned int d1, d2, d3, d4; + unsigned int d1=256, d2=256, d3=256, d4=256; argp=0; /* Silence unused parameter warning. */ diff --git a/Source/CursesDialog/form/fty_regex.c b/Source/CursesDialog/form/fty_regex.c index 0af1cef17..f90e0c108 100644 --- a/Source/CursesDialog/form/fty_regex.c +++ b/Source/CursesDialog/form/fty_regex.c @@ -40,7 +40,7 @@ static char *RegEx_Error(int code) return 0; } -#define INIT register char *sp = RegEx_Init(instring); +#define INIT char *sp = RegEx_Init(instring); #define GETC() (*sp++) #define PEEKC() (*sp) #define UNGETC(c) (--sp) diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 1684fb229..ef252944e 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -11,6 +11,9 @@ #============================================================================= project(QtDialog) +if(POLICY CMP0020) + cmake_policy(SET CMP0020 NEW) # Drop when CMake >= 2.8.11 required +endif() find_package(Qt5Widgets QUIET) if (Qt5Widgets_FOUND) include_directories(${Qt5Widgets_INCLUDE_DIRS}) @@ -29,6 +32,11 @@ if (Qt5Widgets_FOUND) add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") + + if(WIN32 AND TARGET Qt5::Core) + get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION) + get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH) + endif() else() set(QT_MIN_VERSION "4.4.0") find_package(Qt4 REQUIRED) @@ -38,6 +46,13 @@ else() endif() include(${QT_USE_FILE}) + + if(WIN32 AND EXISTS "${QT_QMAKE_EXECUTABLE}") + get_filename_component(_Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH) + if(EXISTS "${_Qt_BIN_DIR}/QtCore4.dll") + set(Qt_BIN_DIR ${_Qt_BIN_DIR}) + endif() + endif() endif() set(SRCS @@ -91,6 +106,9 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS}) target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${QT_LIBRARIES}) +if(Qt_BIN_DIR) + set_property(TARGET cmake-gui PROPERTY Qt_BIN_DIR ${Qt_BIN_DIR}) +endif() if(APPLE) set_target_properties(cmake-gui PROPERTIES diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index c0dde1c2c..4d62f7263 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -28,6 +28,7 @@ #include <QShortcut> #include <QKeySequence> #include <QMacInstallDialog.h> +#include <QInputDialog> #include "QCMake.h" #include "QCMakeCacheView.h" @@ -122,6 +123,22 @@ CMakeSetupDialog::CMakeSetupDialog() QObject::connect(this->InstallForCommandLineAction, SIGNAL(triggered(bool)), this, SLOT(doInstallForCommandLine())); #endif + ToolsMenu->addSeparator(); + ToolsMenu->addAction(tr("&Find in Output..."), + this, SLOT(doOutputFindDialog()), + QKeySequence::Find); + ToolsMenu->addAction(tr("Find Next"), + this, SLOT(doOutputFindNext()), + QKeySequence::FindNext); + ToolsMenu->addAction(tr("Find Previous"), + this, SLOT(doOutputFindPrev()), + QKeySequence::FindPrevious); + ToolsMenu->addAction(tr("Goto Next Error"), + this, SLOT(doOutputErrorNext()), + QKeySequence(Qt::Key_F8)); // in Visual Studio + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Period), + this, SLOT(doOutputErrorNext())); // in Eclipse + QMenu* OptionsMenu = this->menuBar()->addMenu(tr("&Options")); this->SuppressDevWarningsAction = OptionsMenu->addAction(tr("&Suppress dev Warnings (-Wno-dev)")); @@ -154,10 +171,6 @@ CMakeSetupDialog::CMakeSetupDialog() QObject::connect(a, SIGNAL(triggered(bool)), this, SLOT(doHelp())); - QShortcut* filterShortcut = new QShortcut(QKeySequence::Find, this); - QObject::connect(filterShortcut, SIGNAL(activated()), - this, SLOT(startSearch())); - this->setAcceptDrops(true); // get the saved binary directories @@ -172,6 +185,10 @@ CMakeSetupDialog::CMakeSetupDialog() this->Output->setFont(outputFont); this->ErrorFormat.setForeground(QBrush(Qt::red)); + this->Output->setContextMenuPolicy(Qt::CustomContextMenu); + connect(this->Output, SIGNAL(customContextMenuRequested(const QPoint&)), + this, SLOT(doOutputContextMenu(const QPoint &))); + // start the cmake worker thread this->CMakeThread = new QCMakeThread(this); QObject::connect(this->CMakeThread, SIGNAL(cmakeInitialized()), @@ -637,7 +654,13 @@ void CMakeSetupDialog::showProgress(const QString& /*msg*/, float percent) void CMakeSetupDialog::error(const QString& msg) { this->Output->setCurrentCharFormat(this->ErrorFormat); - this->Output->append(msg); + //QTextEdit will terminate the msg with a ParagraphSeparator, but it also replaces + //all newlines with ParagraphSeparators. By replacing the newlines by ourself, one + //error msg will be one paragraph. + QString paragraph(msg); + paragraph.replace(QLatin1Char('\n'), QChar::LineSeparator); + this->Output->append(paragraph); + } void CMakeSetupDialog::message(const QString& msg) @@ -1149,4 +1172,134 @@ void CMakeSetupDialog::setSearchFilter(const QString& str) this->CacheValues->setSearchFilter(str); } +void CMakeSetupDialog::doOutputContextMenu(const QPoint &pt) +{ + QMenu *menu = this->Output->createStandardContextMenu(); + + menu->addSeparator(); + menu->addAction(tr("Find..."), + this, SLOT(doOutputFindDialog()), QKeySequence::Find); + menu->addAction(tr("Find Next"), + this, SLOT(doOutputFindNext()), QKeySequence::FindNext); + menu->addAction(tr("Find Previous"), + this, SLOT(doOutputFindPrev()), QKeySequence::FindPrevious); + menu->addSeparator(); + menu->addAction(tr("Goto Next Error"), + this, SLOT(doOutputErrorNext()), QKeySequence(Qt::Key_F8)); + + menu->exec(this->Output->mapToGlobal(pt)); + delete menu; +} + +void CMakeSetupDialog::doOutputFindDialog() +{ + QStringList strings(this->FindHistory); + + QString selection = this->Output->textCursor().selectedText(); + if (!selection.isEmpty() && + !selection.contains(QChar::ParagraphSeparator) && + !selection.contains(QChar::LineSeparator)) + { + strings.push_front(selection); + } + + bool ok; + QString search = QInputDialog::getItem(this, tr("Find in Output"), + tr("Find:"), strings, 0, true, &ok); + if (ok && !search.isEmpty()) + { + if (!this->FindHistory.contains(search)) + { + this->FindHistory.push_front(search); + } + doOutputFindNext(); + } +} + +void CMakeSetupDialog::doOutputFindPrev() +{ + doOutputFindNext(false); +} + +void CMakeSetupDialog::doOutputFindNext(bool directionForward) +{ + if (this->FindHistory.isEmpty()) + { + doOutputFindDialog(); //will re-call this function again + return; + } + + QString search = this->FindHistory.front(); + + QTextCursor cursor = this->Output->textCursor(); + QTextDocument* document = this->Output->document(); + QTextDocument::FindFlags flags; + if (!directionForward) + { + flags |= QTextDocument::FindBackward; + } + + cursor = document->find(search, cursor, flags); + + if (cursor.isNull()) + { + // first search found nothing, wrap around and search again + cursor = this->Output->textCursor(); + cursor.movePosition(directionForward ? QTextCursor::Start + : QTextCursor::End); + cursor = document->find(search, cursor, flags); + } + + if (cursor.hasSelection()) + { + this->Output->setTextCursor(cursor); + } +} + +void CMakeSetupDialog::doOutputErrorNext() +{ + QTextCursor cursor = this->Output->textCursor(); + bool atEnd = false; + // move cursor out of current error-block + if (cursor.blockCharFormat() == this->ErrorFormat) + { + atEnd = !cursor.movePosition(QTextCursor::NextBlock); + } + + // move cursor to next error-block + while (cursor.blockCharFormat() != this->ErrorFormat && !atEnd) + { + atEnd = !cursor.movePosition(QTextCursor::NextBlock); + } + + if (atEnd) + { + // first search found nothing, wrap around and search again + atEnd = !cursor.movePosition(QTextCursor::Start); + + // move cursor to next error-block + while (cursor.blockCharFormat() != this->ErrorFormat && !atEnd) + { + atEnd = !cursor.movePosition(QTextCursor::NextBlock); + } + } + + if (!atEnd) + { + cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + + QTextCharFormat selectionFormat; + selectionFormat.setBackground(Qt::yellow); + QTextEdit::ExtraSelection extraSelection = {cursor, selectionFormat}; + this->Output->setExtraSelections(QList<QTextEdit::ExtraSelection>() + << extraSelection); + + // make the whole error-block visible + this->Output->setTextCursor(cursor); + + // remove the selection to see the extraSelection + cursor.setPosition(cursor.anchor()); + this->Output->setTextCursor(cursor); + } +} diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h index 259967580..963c7d12e 100644 --- a/Source/QtDialog/CMakeSetupDialog.h +++ b/Source/QtDialog/CMakeSetupDialog.h @@ -77,6 +77,11 @@ protected slots: bool doConfigureInternal(); bool doGenerateInternal(); void exitLoop(int); + void doOutputContextMenu(const QPoint &); + void doOutputFindDialog(); + void doOutputFindNext(bool directionForward = true); + void doOutputFindPrev(); + void doOutputErrorNext(); protected: @@ -106,6 +111,7 @@ protected: QTextCharFormat MessageFormat; QStringList AddVariableCompletions; + QStringList FindHistory; QEventLoop LocalLoop; diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui index dc8ee3fbd..98da249d5 100644 --- a/Source/QtDialog/CMakeSetupDialog.ui +++ b/Source/QtDialog/CMakeSetupDialog.ui @@ -107,7 +107,10 @@ </sizepolicy> </property> <property name="text"> - <string>Search:</string> + <string>S&earch:</string> + </property> + <property name="buddy"> + <cstring>Search</cstring> </property> </widget> </item> diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx index 6006758c7..bae6a30a7 100644 --- a/Source/QtDialog/QCMakeCacheView.cxx +++ b/Source/QtDialog/QCMakeCacheView.cxx @@ -177,7 +177,7 @@ QModelIndex QCMakeCacheView::moveCursor(CursorAction act, void QCMakeCacheView::setShowAdvanced(bool s) { #if QT_VERSION >= 040300 - // new 4.3 api that needs to be called. what about an older Qt? + // new 4.3 API that needs to be called. what about an older Qt? this->SearchFilter->invalidate(); #endif diff --git a/Source/cmAddCompileOptionsCommand.cxx b/Source/cmAddCompileOptionsCommand.cxx new file mode 100644 index 000000000..a6c3c005c --- /dev/null +++ b/Source/cmAddCompileOptionsCommand.cxx @@ -0,0 +1,28 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmAddCompileOptionsCommand.h" + +bool cmAddCompileOptionsCommand +::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) +{ + if(args.size() < 1 ) + { + return true; + } + + for(std::vector<std::string>::const_iterator i = args.begin(); + i != args.end(); ++i) + { + this->Makefile->AddCompileOption(i->c_str()); + } + return true; +} diff --git a/Source/cmAddCompileOptionsCommand.h b/Source/cmAddCompileOptionsCommand.h new file mode 100644 index 000000000..e9bbf2816 --- /dev/null +++ b/Source/cmAddCompileOptionsCommand.h @@ -0,0 +1,71 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmAddCompileOptionsCommand_h +#define cmAddCompileOptionsCommand_h + +#include "cmCommand.h" +#include "cmDocumentGeneratorExpressions.h" + +class cmAddCompileOptionsCommand : public cmCommand +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmAddCompileOptionsCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector<std::string> const& args, + cmExecutionStatus &status); + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() const {return "add_compile_options";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() const + { + return "Adds options to the compilation of source files."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() const + { + return + " add_compile_options(<option> ...)\n" + "Adds options to the compiler command line for sources in the " + "current directory and below. This command can be used to add any " + "options, but alternative commands exist to add preprocessor " + "definitions or include directories. " + "See documentation of the directory and target COMPILE_OPTIONS " + "properties for details. " + "Arguments to add_compile_options may use \"generator " + "expressions\" with the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS + ; + } + + cmTypeMacro(cmAddCompileOptionsCommand, cmCommand); +}; + +#endif diff --git a/Source/cmAddDefinitionsCommand.h b/Source/cmAddDefinitionsCommand.h index 7bb37674d..ff2c4a038 100644 --- a/Source/cmAddDefinitionsCommand.h +++ b/Source/cmAddDefinitionsCommand.h @@ -63,7 +63,7 @@ public: "but it was originally intended to add preprocessor definitions. " "Flags beginning in -D or /D that look like preprocessor definitions " "are automatically added to the COMPILE_DEFINITIONS property for " - "the current directory. Definitions with non-trival values may be " + "the current directory. Definitions with non-trivial values may be " "left in the set of flags instead of being converted for reasons of " "backwards compatibility. See documentation of the directory, " "target, and source file COMPILE_DEFINITIONS properties for details " @@ -73,8 +73,6 @@ public: } cmTypeMacro(cmAddDefinitionsCommand, cmCommand); -private: - bool ParseDefinition(std::string const& def); }; diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx index 04a304e39..e4d7f7f1e 100644 --- a/Source/cmAddDependenciesCommand.cxx +++ b/Source/cmAddDependenciesCommand.cxx @@ -24,6 +24,13 @@ bool cmAddDependenciesCommand } std::string target_name = args[0]; + if(this->Makefile->IsAlias(target_name.c_str())) + { + cmOStringStream e; + e << "Cannot add target-level dependencies to alias target \"" + << target_name << "\".\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + } if(cmTarget* target = this->Makefile->FindTargetToUse(target_name.c_str())) { std::vector<std::string>::const_iterator s = args.begin(); diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index 6dd8e5c64..578525969 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -30,6 +30,7 @@ bool cmAddExecutableCommand bool excludeFromAll = false; bool importTarget = false; bool importGlobal = false; + bool isAlias = false; while ( s != args.end() ) { if (*s == "WIN32") @@ -57,6 +58,11 @@ bool cmAddExecutableCommand ++s; importGlobal = true; } + else if(*s == "ALIAS") + { + ++s; + isAlias = true; + } else { break; @@ -83,6 +89,72 @@ bool cmAddExecutableCommand } return false; } + if (isAlias) + { + if(!cmGeneratorExpression::IsValidTargetName(exename.c_str())) + { + this->SetError(("Invalid name for ALIAS: " + exename).c_str()); + return false; + } + if(excludeFromAll) + { + this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense."); + return false; + } + if(importTarget || importGlobal) + { + this->SetError("IMPORTED with ALIAS is not allowed."); + return false; + } + if(args.size() != 3) + { + cmOStringStream e; + e << "ALIAS requires exactly one target argument."; + this->SetError(e.str().c_str()); + return false; + } + + const char *aliasedName = s->c_str(); + if(this->Makefile->IsAlias(aliasedName)) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << exename + << "\" because target \"" << aliasedName << "\" is itself an ALIAS."; + this->SetError(e.str().c_str()); + return false; + } + cmTarget *aliasedTarget = + this->Makefile->FindTargetToUse(aliasedName, true); + if(!aliasedTarget) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << exename + << "\" because target \"" << aliasedName << "\" does not already " + "exist."; + this->SetError(e.str().c_str()); + return false; + } + cmTarget::TargetType type = aliasedTarget->GetType(); + if(type != cmTarget::EXECUTABLE) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << exename + << "\" because target \"" << aliasedName << "\" is not an " + "executable."; + this->SetError(e.str().c_str()); + return false; + } + if(aliasedTarget->IsImported()) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << exename + << "\" because target \"" << aliasedName << "\" is IMPORTED."; + this->SetError(e.str().c_str()); + return false; + } + this->Makefile->AddAlias(exename.c_str(), aliasedTarget); + return true; + } // Handle imported target creation. if(importTarget) diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h index 1e9f9b3be..2774ce841 100644 --- a/Source/cmAddExecutableCommand.h +++ b/Source/cmAddExecutableCommand.h @@ -107,6 +107,19 @@ public: "(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) " "which specifies the location of the main executable file on disk. " "See documentation of the IMPORTED_* properties for more information." + "\n" + "The signature\n" + " add_executable(<name> ALIAS <target>)\n" + "creates an alias, such that <name> can be used to refer to <target> " + "in subsequent commands. The <name> does not appear in the generated " + "buildsystem as a make target. The <target> may not be an IMPORTED " + "target or an ALIAS. Alias targets can be used as linkable targets, " + "targets to read properties from, executables for custom commands and " + "custom targets. They can also be tested for existance with the " + "regular if(TARGET) subcommand. The <name> may not be used to modify " + "properties of <target>, that is, it may not be used as the operand of " + "set_property, set_target_properties, target_link_libraries etc. An " + "ALIAS target may not be installed of exported." ; } diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index fd39eec02..cbc6ed1e9 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -43,6 +43,7 @@ bool cmAddLibraryCommand // the type of library. Otherwise, it is treated as a source or // source list name. There may be two keyword arguments, check for them bool haveSpecifiedType = false; + bool isAlias = false; while ( s != args.end() ) { std::string libType = *s; @@ -76,6 +77,11 @@ bool cmAddLibraryCommand type = cmTarget::UNKNOWN_LIBRARY; haveSpecifiedType = true; } + else if(libType == "ALIAS") + { + ++s; + isAlias = true; + } else if(*s == "EXCLUDE_FROM_ALL") { ++s; @@ -96,6 +102,80 @@ bool cmAddLibraryCommand break; } } + if (isAlias) + { + if(!cmGeneratorExpression::IsValidTargetName(libName.c_str())) + { + this->SetError(("Invalid name for ALIAS: " + libName).c_str()); + return false; + } + if(excludeFromAll) + { + this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense."); + return false; + } + if(importTarget || importGlobal) + { + this->SetError("IMPORTED with ALIAS is not allowed."); + return false; + } + if(args.size() != 3) + { + cmOStringStream e; + e << "ALIAS requires exactly one target argument."; + this->SetError(e.str().c_str()); + return false; + } + + const char *aliasedName = s->c_str(); + if(this->Makefile->IsAlias(aliasedName)) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" is itself an ALIAS."; + this->SetError(e.str().c_str()); + return false; + } + cmTarget *aliasedTarget = + this->Makefile->FindTargetToUse(aliasedName, true); + if(!aliasedTarget) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" does not already " + "exist."; + this->SetError(e.str().c_str()); + return false; + } + cmTarget::TargetType aliasedType = aliasedTarget->GetType(); + if(aliasedType != cmTarget::SHARED_LIBRARY + && aliasedType != cmTarget::STATIC_LIBRARY + && aliasedType != cmTarget::MODULE_LIBRARY + && aliasedType != cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" is not a library."; + this->SetError(e.str().c_str()); + return false; + } + if(aliasedTarget->IsImported()) + { + cmOStringStream e; + e << "cannot create ALIAS target \"" << libName + << "\" because target \"" << aliasedName << "\" is IMPORTED."; + this->SetError(e.str().c_str()); + return false; + } + this->Makefile->AddAlias(libName.c_str(), aliasedTarget); + return true; + } + + if(importTarget && excludeFromAll) + { + this->SetError("excludeFromAll with IMPORTED target makes no sense."); + return false; + } /* ideally we should check whether for the linker language of the target CMAKE_${LANG}_CREATE_SHARED_LIBRARY is defined and if not default to diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h index e5f27cb51..59354b0f5 100644 --- a/Source/cmAddLibraryCommand.h +++ b/Source/cmAddLibraryCommand.h @@ -138,6 +138,19 @@ public: "Some native build systems may not like targets that have only " "object files, so consider adding at least one real source file " "to any target that references $<TARGET_OBJECTS:objlib>." + "\n" + "The signature\n" + " add_library(<name> ALIAS <target>)\n" + "creates an alias, such that <name> can be used to refer to <target> " + "in subsequent commands. The <name> does not appear in the generated " + "buildsystem as a make target. The <target> may not be an IMPORTED " + "target or an ALIAS. Alias targets can be used as linkable targets, " + "targets to read properties from. They can also be tested for " + "existance with the " + "regular if(TARGET) subcommand. The <name> may not be used to modify " + "properties of <target>, that is, it may not be used as the operand of " + "set_property, set_target_properties, target_link_libraries etc. An " + "ALIAS target may not be installed of exported." ; } diff --git a/Source/cmAddSubDirectoryCommand.h b/Source/cmAddSubDirectoryCommand.h index fa322b0c4..e7f907c3f 100644 --- a/Source/cmAddSubDirectoryCommand.h +++ b/Source/cmAddSubDirectoryCommand.h @@ -61,7 +61,7 @@ public: " add_subdirectory(source_dir [binary_dir] \n" " [EXCLUDE_FROM_ALL])\n" "Add a subdirectory to the build. The source_dir specifies the " - "directory in which the source CmakeLists.txt and code files are " + "directory in which the source CMakeLists.txt and code files are " "located. If it is a relative " "path it will be evaluated with respect to the current " "directory (the typical usage), but it may also be an absolute path. " diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h index 6a0cd9d2e..ec7fda3f3 100644 --- a/Source/cmAddTestCommand.h +++ b/Source/cmAddTestCommand.h @@ -71,6 +71,9 @@ public: " add_test(NAME <name> [CONFIGURATIONS [Debug|Release|...]]\n" " [WORKING_DIRECTORY dir]\n" " COMMAND <command> [arg1 [arg2 ...]])\n" + "Add a test called <name>. " + "The test name may not contain spaces, quotes, or other characters " + "special in CMake syntax. " "If COMMAND specifies an executable target (created by " "add_executable) it will automatically be replaced by the location " "of the executable created at build time. " diff --git a/Source/cmBootstrapCommands1.cxx b/Source/cmBootstrapCommands1.cxx new file mode 100644 index 000000000..9093579dc --- /dev/null +++ b/Source/cmBootstrapCommands1.cxx @@ -0,0 +1,91 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +// This file is used to compile all the commands +// that CMake knows about at compile time. +// This is sort of a boot strapping approach since you would +// like to have CMake to build CMake. +#include "cmCommands.h" +#include "cmAddCustomCommandCommand.cxx" +#include "cmAddCustomTargetCommand.cxx" +#include "cmAddDefinitionsCommand.cxx" +#include "cmAddDependenciesCommand.cxx" +#include "cmAddExecutableCommand.cxx" +#include "cmAddLibraryCommand.cxx" +#include "cmAddSubDirectoryCommand.cxx" +#include "cmAddTestCommand.cxx" +#include "cmBreakCommand.cxx" +#include "cmBuildCommand.cxx" +#include "cmCMakeMinimumRequired.cxx" +#include "cmCMakePolicyCommand.cxx" +#include "cmCommandArgumentsHelper.cxx" +#include "cmConfigureFileCommand.cxx" +#include "cmCoreTryCompile.cxx" +#include "cmCreateTestSourceList.cxx" +#include "cmDefinePropertyCommand.cxx" +#include "cmElseCommand.cxx" +#include "cmEnableLanguageCommand.cxx" +#include "cmEnableTestingCommand.cxx" +#include "cmEndForEachCommand.cxx" +#include "cmEndFunctionCommand.cxx" +#include "cmEndIfCommand.cxx" +#include "cmEndMacroCommand.cxx" +#include "cmEndWhileCommand.cxx" +#include "cmExecProgramCommand.cxx" +#include "cmExecuteProcessCommand.cxx" +#include "cmExternalMakefileProjectGenerator.cxx" +#include "cmFindBase.cxx" +#include "cmFindCommon.cxx" +#include "cmFileCommand.cxx" +#include "cmFindFileCommand.cxx" +#include "cmFindLibraryCommand.cxx" +#include "cmFindPackageCommand.cxx" +#include "cmFindPathCommand.cxx" +#include "cmFindProgramCommand.cxx" +#include "cmForEachCommand.cxx" +#include "cmFunctionCommand.cxx" + +void GetBootstrapCommands1(std::list<cmCommand*>& commands) +{ + commands.push_back(new cmAddCustomCommandCommand); + commands.push_back(new cmAddCustomTargetCommand); + commands.push_back(new cmAddDefinitionsCommand); + commands.push_back(new cmAddDependenciesCommand); + commands.push_back(new cmAddExecutableCommand); + commands.push_back(new cmAddLibraryCommand); + commands.push_back(new cmAddSubDirectoryCommand); + commands.push_back(new cmAddTestCommand); + commands.push_back(new cmBreakCommand); + commands.push_back(new cmBuildCommand); + commands.push_back(new cmCMakeMinimumRequired); + commands.push_back(new cmCMakePolicyCommand); + commands.push_back(new cmConfigureFileCommand); + commands.push_back(new cmCreateTestSourceList); + commands.push_back(new cmDefinePropertyCommand); + commands.push_back(new cmElseCommand); + commands.push_back(new cmEnableLanguageCommand); + commands.push_back(new cmEnableTestingCommand); + commands.push_back(new cmEndForEachCommand); + commands.push_back(new cmEndFunctionCommand); + commands.push_back(new cmEndIfCommand); + commands.push_back(new cmEndMacroCommand); + commands.push_back(new cmEndWhileCommand); + commands.push_back(new cmExecProgramCommand); + commands.push_back(new cmExecuteProcessCommand); + commands.push_back(new cmFileCommand); + commands.push_back(new cmFindFileCommand); + commands.push_back(new cmFindLibraryCommand); + commands.push_back(new cmFindPackageCommand); + commands.push_back(new cmFindPathCommand); + commands.push_back(new cmFindProgramCommand); + commands.push_back(new cmForEachCommand); + commands.push_back(new cmFunctionCommand); +} diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands2.cxx index e3a2ad4e5..be72526ba 100644 --- a/Source/cmBootstrapCommands.cxx +++ b/Source/cmBootstrapCommands2.cxx @@ -14,44 +14,7 @@ // This is sort of a boot strapping approach since you would // like to have CMake to build CMake. #include "cmCommands.h" -#include "cmAddCustomCommandCommand.cxx" -#include "cmAddCustomTargetCommand.cxx" -#include "cmAddDefinitionsCommand.cxx" -#include "cmAddDependenciesCommand.cxx" -#include "cmAddExecutableCommand.cxx" -#include "cmAddLibraryCommand.cxx" -#include "cmAddSubDirectoryCommand.cxx" -#include "cmAddTestCommand.cxx" -#include "cmBreakCommand.cxx" -#include "cmBuildCommand.cxx" -#include "cmCMakeMinimumRequired.cxx" -#include "cmCMakePolicyCommand.cxx" -#include "cmCommandArgumentsHelper.cxx" -#include "cmConfigureFileCommand.cxx" -#include "cmCoreTryCompile.cxx" -#include "cmCreateTestSourceList.cxx" -#include "cmDefinePropertyCommand.cxx" -#include "cmElseCommand.cxx" -#include "cmEnableLanguageCommand.cxx" -#include "cmEnableTestingCommand.cxx" -#include "cmEndForEachCommand.cxx" -#include "cmEndFunctionCommand.cxx" -#include "cmEndIfCommand.cxx" -#include "cmEndMacroCommand.cxx" -#include "cmEndWhileCommand.cxx" -#include "cmExecProgramCommand.cxx" -#include "cmExecuteProcessCommand.cxx" -#include "cmExternalMakefileProjectGenerator.cxx" -#include "cmFindBase.cxx" -#include "cmFindCommon.cxx" -#include "cmFileCommand.cxx" -#include "cmFindFileCommand.cxx" -#include "cmFindLibraryCommand.cxx" -#include "cmFindPackageCommand.cxx" -#include "cmFindPathCommand.cxx" -#include "cmFindProgramCommand.cxx" -#include "cmForEachCommand.cxx" -#include "cmFunctionCommand.cxx" +#include "cmGeneratorExpressionEvaluationFile.cxx" #include "cmGetCMakePropertyCommand.cxx" #include "cmGetDirectoryPropertyCommand.cxx" #include "cmGetFilenameComponentCommand.cxx" @@ -95,41 +58,8 @@ #include "cmUnsetCommand.cxx" #include "cmWhileCommand.cxx" -void GetBootstrapCommands(std::list<cmCommand*>& commands) +void GetBootstrapCommands2(std::list<cmCommand*>& commands) { - commands.push_back(new cmAddCustomCommandCommand); - commands.push_back(new cmAddCustomTargetCommand); - commands.push_back(new cmAddDefinitionsCommand); - commands.push_back(new cmAddDependenciesCommand); - commands.push_back(new cmAddExecutableCommand); - commands.push_back(new cmAddLibraryCommand); - commands.push_back(new cmAddSubDirectoryCommand); - commands.push_back(new cmAddTestCommand); - commands.push_back(new cmBreakCommand); - commands.push_back(new cmBuildCommand); - commands.push_back(new cmCMakeMinimumRequired); - commands.push_back(new cmCMakePolicyCommand); - commands.push_back(new cmConfigureFileCommand); - commands.push_back(new cmCreateTestSourceList); - commands.push_back(new cmDefinePropertyCommand); - commands.push_back(new cmElseCommand); - commands.push_back(new cmEnableLanguageCommand); - commands.push_back(new cmEnableTestingCommand); - commands.push_back(new cmEndForEachCommand); - commands.push_back(new cmEndFunctionCommand); - commands.push_back(new cmEndIfCommand); - commands.push_back(new cmEndMacroCommand); - commands.push_back(new cmEndWhileCommand); - commands.push_back(new cmExecProgramCommand); - commands.push_back(new cmExecuteProcessCommand); - commands.push_back(new cmFileCommand); - commands.push_back(new cmFindFileCommand); - commands.push_back(new cmFindLibraryCommand); - commands.push_back(new cmFindPackageCommand); - commands.push_back(new cmFindPathCommand); - commands.push_back(new cmFindProgramCommand); - commands.push_back(new cmForEachCommand); - commands.push_back(new cmFunctionCommand); commands.push_back(new cmGetCMakePropertyCommand); commands.push_back(new cmGetDirectoryPropertyCommand); commands.push_back(new cmGetFilenameComponentCommand); diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index 91d55a5a2..b6e2569a5 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -122,7 +122,7 @@ bool cmBuildCommand // std::string makecommand = this->Makefile->GetLocalGenerator() ->GetGlobalGenerator()->GenerateBuildCommand - (makeprogram, project_name, 0, target, configuration, true, false); + (makeprogram, project_name, 0, 0, target, configuration, true, false); this->Makefile->AddDefinition(variable, makecommand.c_str()); @@ -153,7 +153,7 @@ bool cmBuildCommand std::string makecommand = this->Makefile->GetLocalGenerator() ->GetGlobalGenerator()->GenerateBuildCommand - (makeprogram.c_str(), this->Makefile->GetProjectName(), 0, + (makeprogram.c_str(), this->Makefile->GetProjectName(), 0, 0, 0, configType.c_str(), true, false); if(cacheValue) diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx new file mode 100644 index 000000000..62f238369 --- /dev/null +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -0,0 +1,126 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmCMakeHostSystemInformationCommand.h" + +#include <cmsys/ios/sstream> + +// cmCMakeHostSystemInformation +bool cmCMakeHostSystemInformationCommand +::InitialPass(std::vector<std::string> const &args, cmExecutionStatus &) +{ + size_t current_index = 0; + + if(args.size() < (current_index + 2) || args[current_index] != "RESULT") + { + this->SetError("missing RESULT specification."); + return false; + } + + std::string variable = args[current_index + 1]; + current_index += 2; + + if(args.size() < (current_index + 2) || args[current_index] != "QUERY") + { + this->SetError("missing QUERY specification"); + return false; + } + + cmsys::SystemInformation info; + info.RunCPUCheck(); + info.RunOSCheck(); + info.RunMemoryCheck(); + + std::string result_list; + for(size_t i = current_index + 1; i < args.size(); ++i) + { + std::string key = args[i]; + if(i != current_index + 1) + { + result_list += ";"; + } + std::string value; + if(!this->GetValue(info, key, value)) return false; + + result_list += value; + } + + this->Makefile->AddDefinition(variable.c_str(), result_list.c_str()); + + return true; +} + +bool cmCMakeHostSystemInformationCommand +::GetValue(cmsys::SystemInformation &info, + std::string const& key, std::string &value) +{ + if(key == "NUMBER_OF_LOGICAL_CORES") + { + value = this->ValueToString(info.GetNumberOfLogicalCPU()); + } + else if(key == "NUMBER_OF_PHYSICAL_CORES") + { + value = this->ValueToString(info.GetNumberOfPhysicalCPU()); + } + else if(key == "HOSTNAME") + { + value = this->ValueToString(info.GetHostname()); + } + else if(key == "FQDN") + { + value = this->ValueToString(info.GetFullyQualifiedDomainName()); + } + else if(key == "TOTAL_VIRTUAL_MEMORY") + { + value = this->ValueToString(info.GetTotalVirtualMemory()); + } + else if(key == "AVAILABLE_VIRTUAL_MEMORY") + { + value = this->ValueToString(info.GetAvailableVirtualMemory()); + } + else if(key == "TOTAL_PHYSICAL_MEMORY") + { + value = this->ValueToString(info.GetTotalPhysicalMemory()); + } + else if(key == "AVAILABLE_PHYSICAL_MEMORY") + { + value = this->ValueToString(info.GetAvailablePhysicalMemory()); + } + else + { + std::string e = "does not recognize <key> " + key; + this->SetError(e.c_str()); + return false; + } + + return true; +} + +std::string cmCMakeHostSystemInformationCommand +::ValueToString(size_t value) const +{ + cmsys_ios::stringstream tmp; + tmp << value; + return tmp.str(); +} + +std::string cmCMakeHostSystemInformationCommand +::ValueToString(const char *value) const +{ + std::string safe_string = value ? value : ""; + return safe_string; +} + +std::string cmCMakeHostSystemInformationCommand +::ValueToString(std::string const& value) const +{ + return value; +} diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h new file mode 100644 index 000000000..d1b8700ff --- /dev/null +++ b/Source/cmCMakeHostSystemInformationCommand.h @@ -0,0 +1,102 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmCMakeHostSystemInformationCommand_h +#define cmCMakeHostSystemInformationCommand_h + +#include "cmCommand.h" + +#include <cmsys/SystemInformation.hxx> + +/** \class cmCMakeHostSystemInformationCommand + * \brief Query host system specific information + * + * cmCMakeHostSystemInformationCommand queries system information of + * the sytem on which CMake runs. + */ +class cmCMakeHostSystemInformationCommand : public cmCommand +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmCMakeHostSystemInformationCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector<std::string> const& args, + cmExecutionStatus &status); + + /** + * This determines if the command is invoked when in script mode. + */ + virtual bool IsScriptable() const { return true; } + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() const + { + return "cmake_host_system_information"; + } + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() const + { + return "Query host system specific information."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() const + { + return + " cmake_host_system_information(RESULT <variable> QUERY <key> ...)\n" + "Queries system information of the host system on which cmake runs. " + "One or more <key> can be provided to " + "select the information to be queried. " + "The list of queried values is stored in <variable>.\n" + "<key> can be one of the following values:\n" + " NUMBER_OF_LOGICAL_CORES = Number of logical cores.\n" + " NUMBER_OF_PHYSICAL_CORES = Number of physical cores.\n" + " HOSTNAME = Hostname.\n" + " FQDN = Fully qualified domain name.\n" + " TOTAL_VIRTUAL_MEMORY = " + "Total virtual memory in megabytes.\n" + " AVAILABLE_VIRTUAL_MEMORY = " + "Available virtual memory in megabytes.\n" + " TOTAL_PHYSICAL_MEMORY = " + "Total physical memory in megabytes.\n" + " AVAILABLE_PHYSICAL_MEMORY = " + "Available physical memory in megabytes.\n" + ; + } + + cmTypeMacro(cmCMakeHostSystemInformationCommand, cmCommand); + +private: + bool GetValue(cmsys::SystemInformation &info, + std::string const& key, std::string &value); + + std::string ValueToString(size_t value) const; + std::string ValueToString(const char *value) const; + std::string ValueToString(std::string const& value) const; +}; + +#endif diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 48ae50e42..cb62f21e6 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -422,8 +422,9 @@ int CCONV cmExecuteCommand(void *arg, const char *name, for(int i = 0; i < numArgs; ++i) { // Assume all arguments are quoted. - lff.Arguments.push_back(cmListFileArgument(args[i], true, - "[CMake-Plugin]", 0)); + lff.Arguments.push_back( + cmListFileArgument(args[i], cmListFileArgument::Quoted, + "[CMake-Plugin]", 0)); } cmExecutionStatus status; return mf->ExecuteCommand(lff,status); diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 322a6a26f..14e1f5014 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -175,7 +175,7 @@ std::string cmCTest::GetCostDataFile() static size_t HTTPResponseCallback(void *ptr, size_t size, size_t nmemb, void *data) { - register int realsize = (int)(size * nmemb); + int realsize = (int)(size * nmemb); std::string *response = static_cast<std::string*>(data); @@ -294,6 +294,7 @@ cmCTest::cmCTest() { this->LabelSummary = true; this->ParallelLevel = 1; + this->ParallelLevelSetInCli = false; this->SubmitIndex = 0; this->Failover = false; this->BatchJobs = false; @@ -1999,11 +2000,13 @@ void cmCTest::HandleCommandLineArguments(size_t &i, i++; int plevel = atoi(args[i].c_str()); this->SetParallelLevel(plevel); + this->ParallelLevelSetInCli = true; } else if(arg.find("-j") == 0) { int plevel = atoi(arg.substr(2).c_str()); this->SetParallelLevel(plevel); + this->ParallelLevelSetInCli = true; } if(this->CheckArgument(arg, "--no-compress-output")) @@ -2398,6 +2401,14 @@ int cmCTest::Run(std::vector<std::string> &args, std::string* output) } } // the close of the for argument loop + if (!this->ParallelLevelSetInCli) + { + if (const char *parallel = cmSystemTools::GetEnv("CTEST_PARALLEL_LEVEL")) + { + int plevel = atoi(parallel); + this->SetParallelLevel(plevel); + } + } // now what sould cmake do? if --build-and-test was specified then // we run the build and test handler and return @@ -2413,7 +2424,7 @@ int cmCTest::Run(std::vector<std::string> &args, std::string* output) #endif if(retv != 0) { - cmCTestLog(this, DEBUG, "build and test failing returing: " << retv + cmCTestLog(this, DEBUG, "build and test failing returning: " << retv << std::endl); } return retv; diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 587a6db51..5dd35ce41 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -485,6 +485,7 @@ private: int MaxTestNameWidth; int ParallelLevel; + bool ParallelLevelSetInCli; int CompatibilityMode; diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 3d5b24b84..ed09545cb 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -491,7 +491,7 @@ bool cmCacheManager::SaveCache(const char* path) << "# The syntax for the file is as follows:\n" << "# KEY:TYPE=VALUE\n" << "# KEY is the name of a variable in the cache.\n" - << "# TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT " + << "# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT " "TYPE!." << std::endl << "# VALUE is the current value for the KEY.\n\n"; @@ -750,6 +750,10 @@ void cmCacheManager::AddCacheEntry(const char* key, } e.SetProperty("HELPSTRING", helpString? helpString : "(This variable does not exist and should not be used)"); + if (this->Cache[key].Value == e.Value) + { + this->CMakeInstance->UnwatchUnusedCli(key); + } this->Cache[key] = e; } diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index 4a5ee450f..a5e5eeeff 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -82,7 +82,7 @@ public: { this->Find(key); } - } + } private: CacheEntry const& GetEntry() const { return this->Position->second; } CacheEntry& GetEntry() { return this->Position->second; } diff --git a/Source/cmCommandArgumentLexer.cxx b/Source/cmCommandArgumentLexer.cxx index 1d7140bb2..e68f6b5fd 100644 --- a/Source/cmCommandArgumentLexer.cxx +++ b/Source/cmCommandArgumentLexer.cxx @@ -730,9 +730,9 @@ extern int cmCommandArgument_yylex (yyscan_t yyscanner); */ YY_DECL { - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; #line 64 "cmCommandArgumentLexer.in.l" @@ -782,7 +782,7 @@ YY_DECL yy_match: do { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1082,9 +1082,9 @@ return 0; /* this should not happend but it should silence a warning */ static int yy_get_next_buffer (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = yyg->yytext_ptr; - register int number_to_move, i; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = yyg->yytext_ptr; + int number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) @@ -1216,15 +1216,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner) static yy_state_type yy_get_previous_state (yyscan_t yyscanner) { - register yy_state_type yy_current_state; - register char *yy_cp; + yy_state_type yy_current_state; + char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_current_state = yyg->yy_start; for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1249,11 +1249,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) { - register int yy_is_jam; + int yy_is_jam; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ - register char *yy_cp = yyg->yy_c_buf_p; + char *yy_cp = yyg->yy_c_buf_p; - register YY_CHAR yy_c = 1; + YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -2015,7 +2015,7 @@ int cmCommandArgument_yylex_destroy (yyscan_t yyscanner) #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) { - register int i; + int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } @@ -2024,7 +2024,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) { - register int n; + int n; for ( n = 0; s[n]; ++n ) ; diff --git a/Source/cmCommandArgumentLexer.in.l b/Source/cmCommandArgumentLexer.in.l index fdca61bfa..24a0eec85 100644 --- a/Source/cmCommandArgumentLexer.in.l +++ b/Source/cmCommandArgumentLexer.in.l @@ -22,6 +22,7 @@ Modify cmCommandArgumentLexer.cxx: - add #include "cmStandardIncludes.h" to top of file - put header block at top of file - remove TABs + - remove use of the 'register' storage class specifier - remove "yyscanner" argument from these methods: yy_fatal_error, cmCommandArgument_yyalloc, cmCommandArgument_yyrealloc, cmCommandArgument_yyfree - remove all YY_BREAK lines occurring right after return statements diff --git a/Source/cmCommandArgumentParser.y b/Source/cmCommandArgumentParser.y index 3e700c80b..48f5c8ecd 100644 --- a/Source/cmCommandArgumentParser.y +++ b/Source/cmCommandArgumentParser.y @@ -20,6 +20,7 @@ Run bison like this: Modify cmCommandArgumentParser.cxx: - remove TABs + - remove use of the 'register' storage class specifier - put header block at top of file */ diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index 2f26b0cd4..dbeeb0793 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -12,10 +12,10 @@ #include "cmCommandArgumentParserHelper.h" #include "cmSystemTools.h" -#include "cmCommandArgumentLexer.h" - #include "cmMakefile.h" +#include "cmCommandArgumentLexer.h" + int cmCommandArgument_yyparse( yyscan_t yyscanner ); // cmCommandArgumentParserHelper::cmCommandArgumentParserHelper() diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 227b22678..1e2a85cfb 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -11,8 +11,10 @@ ============================================================================*/ #include "cmCommands.h" #if defined(CMAKE_BUILD_WITH_CMAKE) +#include "cmAddCompileOptionsCommand.cxx" #include "cmAuxSourceDirectoryCommand.cxx" #include "cmBuildNameCommand.cxx" +#include "cmCMakeHostSystemInformationCommand.cxx" #include "cmElseIfCommand.cxx" #include "cmExportCommand.cxx" #include "cmExportLibraryDependencies.cxx" @@ -29,6 +31,7 @@ #include "cmSourceGroupCommand.cxx" #include "cmSubdirDependsCommand.cxx" #include "cmTargetCompileDefinitionsCommand.cxx" +#include "cmTargetCompileOptionsCommand.cxx" #include "cmTargetIncludeDirectoriesCommand.cxx" #include "cmTargetPropCommandBase.cxx" #include "cmUseMangledMesaCommand.cxx" @@ -51,8 +54,10 @@ void GetPredefinedCommands(std::list<cmCommand*>& ) { #if defined(CMAKE_BUILD_WITH_CMAKE) + commands.push_back(new cmAddCompileOptionsCommand); commands.push_back(new cmAuxSourceDirectoryCommand); commands.push_back(new cmBuildNameCommand); + commands.push_back(new cmCMakeHostSystemInformationCommand); commands.push_back(new cmElseIfCommand); commands.push_back(new cmExportCommand); commands.push_back(new cmExportLibraryDependenciesCommand); @@ -71,6 +76,7 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands.push_back(new cmSubdirDependsCommand); commands.push_back(new cmTargetIncludeDirectoriesCommand); commands.push_back(new cmTargetCompileDefinitionsCommand); + commands.push_back(new cmTargetCompileOptionsCommand); commands.push_back(new cmUseMangledMesaCommand); commands.push_back(new cmUtilitySourceCommand); commands.push_back(new cmVariableRequiresCommand); diff --git a/Source/cmCommands.h b/Source/cmCommands.h index 096fc2006..c56673fed 100644 --- a/Source/cmCommands.h +++ b/Source/cmCommands.h @@ -16,12 +16,13 @@ class cmCommand; /** * Global function to return all compiled in commands. - * To add a new command edit cmCommands.cxx or cmBootstrapCommands.cxx + * To add a new command edit cmCommands.cxx or cmBootstrapCommands[12].cxx * and add your command. * It is up to the caller to delete the commands created by this * call. */ -void GetBootstrapCommands(std::list<cmCommand*>& commands); +void GetBootstrapCommands1(std::list<cmCommand*>& commands); +void GetBootstrapCommands2(std::list<cmCommand*>& commands); void GetPredefinedCommands(std::list<cmCommand*>& commands); diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 896b50aa5..fb7b5b67d 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -499,7 +499,7 @@ bool cmComputeLinkInformation::Compute() if(!this->LinkLanguage) { cmSystemTools:: - Error("CMake can not determine linker language for target:", + Error("CMake can not determine linker language for target: ", this->Target->GetName()); return false; } @@ -882,7 +882,8 @@ void cmComputeLinkInformation::ComputeItemParserInfo() } // Compute a regex to match link extensions. - std::string libext = this->CreateExtensionRegex(this->LinkExtensions); + std::string libext = this->CreateExtensionRegex(this->LinkExtensions, + LinkUnknown); // Create regex to remove any library extension. std::string reg("(.*)"); @@ -916,7 +917,8 @@ void cmComputeLinkInformation::ComputeItemParserInfo() if(!this->StaticLinkExtensions.empty()) { std::string reg_static = reg; - reg_static += this->CreateExtensionRegex(this->StaticLinkExtensions); + reg_static += this->CreateExtensionRegex(this->StaticLinkExtensions, + LinkStatic); #ifdef CM_COMPUTE_LINK_INFO_DEBUG fprintf(stderr, "static regex [%s]\n", reg_static.c_str()); #endif @@ -928,7 +930,7 @@ void cmComputeLinkInformation::ComputeItemParserInfo() { std::string reg_shared = reg; this->SharedRegexString = - this->CreateExtensionRegex(this->SharedLinkExtensions); + this->CreateExtensionRegex(this->SharedLinkExtensions, LinkShared); reg_shared += this->SharedRegexString; #ifdef CM_COMPUTE_LINK_INFO_DEBUG fprintf(stderr, "shared regex [%s]\n", reg_shared.c_str()); @@ -966,7 +968,7 @@ void cmComputeLinkInformation::AddLinkExtension(const char* e, LinkType type) //---------------------------------------------------------------------------- std::string cmComputeLinkInformation -::CreateExtensionRegex(std::vector<std::string> const& exts) +::CreateExtensionRegex(std::vector<std::string> const& exts, LinkType type) { // Build a list of extension choices. std::string libext = "("; @@ -995,6 +997,10 @@ cmComputeLinkInformation { libext += "(\\.[0-9]+\\.[0-9]+)?"; } + else if(type == LinkShared) + { + libext += "(\\.[0-9]+)?"; + } libext += "$"; return libext; @@ -1339,12 +1345,23 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item) return; } + std::string fw_path = this->SplitFramework.match(1); + std::string fw = this->SplitFramework.match(2); + std::string full_fw = fw_path; + full_fw += "/"; + full_fw += fw; + full_fw += ".framework"; + full_fw += "/"; + full_fw += fw; + // Add the directory portion to the framework search path. - this->AddFrameworkPath(this->SplitFramework.match(1)); + this->AddFrameworkPath(fw_path); + + // add runtime information + this->AddLibraryRuntimeInfo(full_fw); // Add the item using the -framework option. this->Items.push_back(Item("-framework", false)); - std::string fw = this->SplitFramework.match(2); fw = this->LocalGenerator->EscapeForShell(fw.c_str()); this->Items.push_back(Item(fw, false)); } @@ -1724,6 +1741,17 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath, cmTarget* target) { + // Ignore targets on Apple where install_name is not @rpath. + // The dependenty library can be found with other means such as + // @loader_path or full paths. + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + if(!target->HasMacOSXRpath(this->Config)) + { + return; + } + } + // Libraries with unknown type must be handled using just the file // on disk. if(target->GetType() == cmTarget::UNKNOWN_LIBRARY) @@ -1756,25 +1784,61 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath) { // Get the name of the library from the file name. + bool is_shared_library = false; std::string file = cmSystemTools::GetFilenameName(fullPath); - if(!this->ExtractSharedLibraryName.find(file.c_str())) + + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + // Check that @rpath is part of the install name. + // If it isn't, return. + std::string soname; + if(!cmSystemTools::GuessLibraryInstallName(fullPath, soname)) + { + return; + } + + if(soname.find("@rpath") == std::string::npos) + { + return; + } + } + + is_shared_library = this->ExtractSharedLibraryName.find(file.c_str()); + + if(!is_shared_library) { // On some platforms (AIX) a shared library may look static. if(this->ArchivesMayBeShared) { - if(!this->ExtractStaticLibraryName.find(file.c_str())) + if(this->ExtractStaticLibraryName.find(file.c_str())) { - // This is not the name of a shared library or archive. - return; + // This is the name of a shared library or archive. + is_shared_library = true; } } - else + } + + // It could be an Apple framework + if(!is_shared_library) + { + if(fullPath.find(".framework") != std::string::npos) { - // This is not the name of a shared library. - return; + cmsys::RegularExpression splitFramework; + splitFramework.compile("^(.*)/(.*).framework/(.*)$"); + if(splitFramework.find(fullPath) && + (std::string::npos != + splitFramework.match(3).find(splitFramework.match(2)))) + { + is_shared_library = true; + } } } + if(!is_shared_library) + { + return; + } + // Include this library in the runtime path ordering. this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath); if(this->LinkWithRuntimePath) diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 1a76922a5..e6ee87185 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -134,7 +134,8 @@ private: bool OpenBSD; void AddLinkPrefix(const char* p); void AddLinkExtension(const char* e, LinkType type); - std::string CreateExtensionRegex(std::vector<std::string> const& exts); + std::string CreateExtensionRegex(std::vector<std::string> const& exts, + LinkType type); std::string NoCaseExpression(const char* str); // Handling of link items. diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 8fd95b9cd..0829add20 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -282,6 +282,8 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index, if(emitted.insert(*lib).second) { this->AddTargetDepend(depender_index, lib->c_str(), true); + this->AddInterfaceDepends(depender_index, lib->c_str(), + true, emitted); } } } diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index 114afd7b7..ab53b1d27 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -19,4 +19,4 @@ #cmakedefine CMAKE_STRICT #define CMAKE_ROOT_DIR "${CMake_SOURCE_DIR}" #define CMAKE_BUILD_DIR "${CMake_BINARY_DIR}" -#define CMAKE_DATA_DIR "@CMAKE_DATA_DIR@" +#define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@" diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 85e49a928..086f27a58 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -12,6 +12,7 @@ #include "cmCoreTryCompile.h" #include "cmake.h" #include "cmCacheManager.h" +#include "cmLocalGenerator.h" #include "cmGlobalGenerator.h" #include "cmExportTryCompileFileGenerator.h" #include <cmsys/Directory.hxx> @@ -23,150 +24,170 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) this->BinaryDirectory = argv[1].c_str(); this->OutputFile = ""; // which signature were we called with ? - this->SrcFileSignature = false; - unsigned int i; + this->SrcFileSignature = true; const char* sourceDirectory = argv[2].c_str(); const char* projectName = 0; const char* targetName = 0; - char targetNameBuf[64]; - int extraArgs = 0; - - // look for CMAKE_FLAGS and store them std::vector<std::string> cmakeFlags; - for (i = 3; i < argv.size(); ++i) - { - if (argv[i] == "CMAKE_FLAGS") - { - // CMAKE_FLAGS is the first argument because we need an argv[0] that - // is not used, so it matches regular command line parsing which has - // the program name as arg 0 - for (; i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" && - argv[i] != "OUTPUT_VARIABLE" && - argv[i] != "LINK_LIBRARIES"; - ++i) - { - extraArgs++; - cmakeFlags.push_back(argv[i]); - } - break; - } - } - - // look for OUTPUT_VARIABLE and store them + std::vector<std::string> compileDefs; std::string outputVariable; - for (i = 3; i < argv.size(); ++i) + std::string copyFile; + std::string copyFileError; + std::vector<cmTarget*> targets; + std::string libsToLink = " "; + bool useOldLinkLibs = true; + char targetNameBuf[64]; + bool didOutputVariable = false; + bool didCopyFile = false; + bool didCopyFileError = false; + bool useSources = argv[2] == "SOURCES"; + std::vector<std::string> sources; + + enum Doing { DoingNone, DoingCMakeFlags, DoingCompileDefinitions, + DoingLinkLibraries, DoingOutputVariable, DoingCopyFile, + DoingCopyFileError, DoingSources }; + Doing doing = useSources? DoingSources : DoingNone; + for(size_t i=3; i < argv.size(); ++i) { - if (argv[i] == "OUTPUT_VARIABLE") + if(argv[i] == "CMAKE_FLAGS") { - if ( argv.size() <= (i+1) ) - { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, - "OUTPUT_VARIABLE specified but there is no variable"); - return -1; - } - extraArgs += 2; - outputVariable = argv[i+1]; - break; + doing = DoingCMakeFlags; + // CMAKE_FLAGS is the first argument because we need an argv[0] that + // is not used, so it matches regular command line parsing which has + // the program name as arg 0 + cmakeFlags.push_back(argv[i]); } - } - - // look for COMPILE_DEFINITIONS and store them - std::vector<std::string> compileFlags; - for (i = 3; i < argv.size(); ++i) - { - if (argv[i] == "COMPILE_DEFINITIONS") + else if(argv[i] == "COMPILE_DEFINITIONS") { - extraArgs++; - for (i = i + 1; i < argv.size() && argv[i] != "CMAKE_FLAGS" && - argv[i] != "OUTPUT_VARIABLE" && - argv[i] != "LINK_LIBRARIES"; - ++i) - { - extraArgs++; - compileFlags.push_back(argv[i]); - } - break; + doing = DoingCompileDefinitions; } - } - - std::vector<cmTarget*> targets; - std::string libsToLink = " "; - bool useOldLinkLibs = true; - for (i = 3; i < argv.size(); ++i) - { - if (argv[i] == "LINK_LIBRARIES") + else if(argv[i] == "LINK_LIBRARIES") { - if ( argv.size() <= (i+1) ) - { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, - "LINK_LIBRARIES specified but there is no content"); - return -1; - } - extraArgs++; - ++i; + doing = DoingLinkLibraries; useOldLinkLibs = false; - for ( ; i < argv.size() && argv[i] != "CMAKE_FLAGS" - && argv[i] != "COMPILE_DEFINITIONS" && argv[i] != "OUTPUT_VARIABLE"; - ++i) + } + else if(argv[i] == "OUTPUT_VARIABLE") + { + doing = DoingOutputVariable; + didOutputVariable = true; + } + else if(argv[i] == "COPY_FILE") + { + doing = DoingCopyFile; + didCopyFile = true; + } + else if(argv[i] == "COPY_FILE_ERROR") + { + doing = DoingCopyFileError; + didCopyFileError = true; + } + else if(doing == DoingCMakeFlags) + { + cmakeFlags.push_back(argv[i]); + } + else if(doing == DoingCompileDefinitions) + { + compileDefs.push_back(argv[i]); + } + else if(doing == DoingLinkLibraries) + { + libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" "; + if(cmTarget *tgt = this->Makefile->FindTargetToUse(argv[i].c_str())) { - extraArgs++; - libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" "; - cmTarget *tgt = this->Makefile->FindTargetToUse(argv[i].c_str()); - if (!tgt) - { - continue; - } switch(tgt->GetType()) - { - case cmTarget::SHARED_LIBRARY: - case cmTarget::STATIC_LIBRARY: - case cmTarget::UNKNOWN_LIBRARY: - break; - case cmTarget::EXECUTABLE: - if (tgt->IsExecutableWithExports()) - { + { + case cmTarget::SHARED_LIBRARY: + case cmTarget::STATIC_LIBRARY: + case cmTarget::UNKNOWN_LIBRARY: break; - } - default: - this->Makefile->IssueMessage(cmake::FATAL_ERROR, - "Only libraries may be used as try_compile IMPORTED " - "LINK_LIBRARIES. Got " + std::string(tgt->GetName()) + " of " - "type " + tgt->GetTargetTypeName(tgt->GetType()) + "."); - return -1; - } - if (!tgt->IsImported()) + case cmTarget::EXECUTABLE: + if (tgt->IsExecutableWithExports()) + { + break; + } + default: + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "Only libraries may be used as try_compile IMPORTED " + "LINK_LIBRARIES. Got " + std::string(tgt->GetName()) + " of " + "type " + tgt->GetTargetTypeName(tgt->GetType()) + "."); + return -1; + } + if (tgt->IsImported()) { - continue; + targets.push_back(tgt); } - targets.push_back(tgt); } - break; + } + else if(doing == DoingOutputVariable) + { + outputVariable = argv[i].c_str(); + doing = DoingNone; + } + else if(doing == DoingCopyFile) + { + copyFile = argv[i].c_str(); + doing = DoingNone; + } + else if(doing == DoingCopyFileError) + { + copyFileError = argv[i].c_str(); + doing = DoingNone; + } + else if(doing == DoingSources) + { + sources.push_back(argv[i]); + } + else if(i == 3) + { + this->SrcFileSignature = false; + projectName = argv[i].c_str(); + } + else if(i == 4 && !this->SrcFileSignature) + { + targetName = argv[i].c_str(); + } + else + { + cmOStringStream m; + m << "try_compile given unknown argument \"" << argv[i] << "\"."; + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str()); } } - // look for COPY_FILE - std::string copyFile; - for (i = 3; i < argv.size(); ++i) + if(didCopyFile && copyFile.empty()) { - if (argv[i] == "COPY_FILE") - { - if ( argv.size() <= (i+1) ) - { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, - "COPY_FILE specified but there is no variable"); - return -1; - } - extraArgs += 2; - copyFile = argv[i+1]; - break; - } + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "COPY_FILE must be followed by a file path"); + return -1; + } + + if(didCopyFileError && copyFileError.empty()) + { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "COPY_FILE_ERROR must be followed by a variable name"); + return -1; + } + + if(didCopyFileError && !didCopyFile) + { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "COPY_FILE_ERROR may be used only with COPY_FILE"); + return -1; + } + + if(didOutputVariable && outputVariable.empty()) + { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "OUTPUT_VARIABLE must be followed by a variable name"); + return -1; } - // do we have a srcfile signature - if (argv.size() - extraArgs == 3) + if(useSources && sources.empty()) { - this->SrcFileSignature = true; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "SOURCES must be followed by at least one source file"); + return -1; } // compute the binary dir when TRY_COMPILE is called with a src file @@ -179,10 +200,10 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) else { // only valid for srcfile signatures - if (compileFlags.size()) + if (compileDefs.size()) { this->Makefile->IssueMessage(cmake::FATAL_ERROR, - "COMPILE_FLAGS specified on a srcdir type TRY_COMPILE"); + "COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE"); return -1; } if (copyFile.size()) @@ -213,6 +234,44 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) std::string ccFile = this->BinaryDirectory + "/CMakeCache.txt"; cmSystemTools::RemoveFile(ccFile.c_str()); + // Choose sources. + if(!useSources) + { + sources.push_back(argv[2]); + } + + // Detect languages to enable. + cmLocalGenerator* lg = this->Makefile->GetLocalGenerator(); + cmGlobalGenerator* gg = lg->GetGlobalGenerator(); + std::set<std::string> testLangs; + for(std::vector<std::string>::iterator si = sources.begin(); + si != sources.end(); ++si) + { + std::string ext = cmSystemTools::GetFilenameLastExtension(*si); + if(const char* lang = gg->GetLanguageFromExtension(ext.c_str())) + { + testLangs.insert(lang); + } + else + { + cmOStringStream err; + err << "Unknown extension \"" << ext << "\" for file\n" + << " " << *si << "\n" + << "try_compile() works only for enabled languages. " + << "Currently these are:\n "; + std::vector<std::string> langs; + gg->GetEnabledLanguages(langs); + for(std::vector<std::string>::iterator l = langs.begin(); + l != langs.end(); ++l) + { + err << " " << *l; + } + err << "\nSee project() command to enable other languages."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, err.str()); + return -1; + } + } + // we need to create a directory and CMakeLists file etc... // first create the directories sourceDirectory = this->BinaryDirectory.c_str(); @@ -229,10 +288,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) return -1; } - std::string source = argv[2]; - std::string ext = cmSystemTools::GetFilenameLastExtension(source); - const char* lang =(this->Makefile->GetCMakeInstance()->GetGlobalGenerator() - ->GetLanguageFromExtension(ext.c_str())); const char* def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH"); fprintf(fout, "cmake_minimum_required(VERSION %u.%u.%u.%u)\n", cmVersion::GetMajorVersion(), cmVersion::GetMinorVersion(), @@ -242,67 +297,48 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) fprintf(fout, "SET(CMAKE_MODULE_PATH %s)\n", def); } - const char* rulesOverrideBase = "CMAKE_USER_MAKE_RULES_OVERRIDE"; - std::string rulesOverrideLang = - rulesOverrideBase + (lang ? std::string("_") + lang : std::string("")); - if(const char* rulesOverridePath = - this->Makefile->GetDefinition(rulesOverrideLang.c_str())) - { - fprintf(fout, "SET(%s \"%s\")\n", - rulesOverrideLang.c_str(), rulesOverridePath); - } - else if(const char* rulesOverridePath2 = - this->Makefile->GetDefinition(rulesOverrideBase)) - { - fprintf(fout, "SET(%s \"%s\")\n", - rulesOverrideBase, rulesOverridePath2); - } - - if(lang) + std::string projectLangs; + for(std::set<std::string>::iterator li = testLangs.begin(); + li != testLangs.end(); ++li) { - fprintf(fout, "PROJECT(CMAKE_TRY_COMPILE %s)\n", lang); - } - else - { - fclose(fout); - cmOStringStream err; - err << "Unknown extension \"" << ext << "\" for file\n" - << " " << source << "\n" - << "try_compile() works only for enabled languages. " - << "Currently these are:\n "; - std::vector<std::string> langs; - this->Makefile->GetCMakeInstance()->GetGlobalGenerator()-> - GetEnabledLanguages(langs); - for(std::vector<std::string>::iterator l = langs.begin(); - l != langs.end(); ++l) + projectLangs += " " + *li; + std::string rulesOverrideBase = "CMAKE_USER_MAKE_RULES_OVERRIDE"; + std::string rulesOverrideLang = rulesOverrideBase + "_" + *li; + if(const char* rulesOverridePath = + this->Makefile->GetDefinition(rulesOverrideLang.c_str())) { - err << " " << *l; + fprintf(fout, "SET(%s \"%s\")\n", + rulesOverrideLang.c_str(), rulesOverridePath); + } + else if(const char* rulesOverridePath2 = + this->Makefile->GetDefinition(rulesOverrideBase.c_str())) + { + fprintf(fout, "SET(%s \"%s\")\n", + rulesOverrideBase.c_str(), rulesOverridePath2); } - err << "\nSee project() command to enable other languages."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, err.str()); - return -1; } - std::string langFlags = "CMAKE_"; - langFlags += lang; - langFlags += "_FLAGS"; + fprintf(fout, "PROJECT(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str()); fprintf(fout, "SET(CMAKE_VERBOSE_MAKEFILE 1)\n"); - fprintf(fout, "SET(CMAKE_%s_FLAGS \"", lang); - const char* flags = this->Makefile->GetDefinition(langFlags.c_str()); - if(flags) + for(std::set<std::string>::iterator li = testLangs.begin(); + li != testLangs.end(); ++li) { - fprintf(fout, " %s ", flags); + std::string langFlags = "CMAKE_" + *li + "_FLAGS"; + const char* flags = this->Makefile->GetDefinition(langFlags.c_str()); + fprintf(fout, "SET(CMAKE_%s_FLAGS %s)\n", li->c_str(), + lg->EscapeForCMake(flags?flags:"").c_str()); + fprintf(fout, "SET(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}" + " ${COMPILE_DEFINITIONS}\")\n", li->c_str(), li->c_str()); } - fprintf(fout, " ${COMPILE_DEFINITIONS}\")\n"); fprintf(fout, "INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES})\n"); fprintf(fout, "SET(CMAKE_SUPPRESS_REGENERATION 1)\n"); fprintf(fout, "LINK_DIRECTORIES(${LINK_DIRECTORIES})\n"); // handle any compile flags we need to pass on - if (compileFlags.size()) + if (compileDefs.size()) { fprintf(fout, "ADD_DEFINITIONS( "); - for (i = 0; i < compileFlags.size(); ++i) + for (size_t i = 0; i < compileDefs.size(); ++i) { - fprintf(fout,"%s ",compileFlags[i].c_str()); + fprintf(fout,"%s ",compileDefs[i].c_str()); } fprintf(fout, ")\n"); } @@ -377,7 +413,19 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) fprintf(fout, "SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n", this->BinaryDirectory.c_str()); /* Create the actual executable. */ - fprintf(fout, "ADD_EXECUTABLE(%s \"%s\")\n", targetName, source.c_str()); + fprintf(fout, "ADD_EXECUTABLE(%s", targetName); + for(std::vector<std::string>::iterator si = sources.begin(); + si != sources.end(); ++si) + { + fprintf(fout, " \"%s\"", si->c_str()); + + // Add dependencies on any non-temporary sources. + if(si->find("CMakeTmp") == si->npos) + { + this->Makefile->AddCMakeDependFile(*si); + } + } + fprintf(fout, ")\n"); if (useOldLinkLibs) { fprintf(fout, @@ -391,22 +439,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) } fclose(fout); projectName = "CMAKE_TRY_COMPILE"; - // if the source is not in CMakeTmp - if(source.find("CMakeTmp") == source.npos) - { - this->Makefile->AddCMakeDependFile(source.c_str()); - } - - } - // else the srcdir bindir project target signature - else - { - projectName = argv[3].c_str(); - - if (argv.size() - extraArgs == 5) - { - targetName = argv[4].c_str(); - } } bool erroroc = cmSystemTools::GetErrorOccuredFlag(); @@ -438,6 +470,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) if (this->SrcFileSignature) { + std::string copyFileErrorMessage; this->FindOutputFile(targetName); if ((res==0) && (copyFile.size())) @@ -455,10 +488,23 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) { emsg << this->FindErrorMessage.c_str(); } - this->Makefile->IssueMessage(cmake::FATAL_ERROR, emsg.str()); - return -1; + if(copyFileError.empty()) + { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, emsg.str()); + return -1; + } + else + { + copyFileErrorMessage = emsg.str(); + } } } + + if(!copyFileError.empty()) + { + this->Makefile->AddDefinition(copyFileError.c_str(), + copyFileErrorMessage.c_str()); + } } return res; } diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx index bd860ee6a..3620a3895 100644 --- a/Source/cmCustomCommand.cxx +++ b/Source/cmCustomCommand.cxx @@ -13,6 +13,8 @@ #include "cmMakefile.h" +#include <cmsys/auto_ptr.hxx> + //---------------------------------------------------------------------------- cmCustomCommand::cmCustomCommand() { @@ -36,6 +38,32 @@ cmCustomCommand::cmCustomCommand(const cmCustomCommand& r): } //---------------------------------------------------------------------------- +cmCustomCommand& cmCustomCommand::operator=(cmCustomCommand const& r) +{ + if(this == &r) + { + return *this; + } + + this->Outputs = r.Outputs; + this->Depends = r.Depends; + this->CommandLines = r.CommandLines; + this->HaveComment = r.HaveComment; + this->Comment = r.Comment; + this->WorkingDirectory = r.WorkingDirectory; + this->EscapeAllowMakeVars = r.EscapeAllowMakeVars; + this->EscapeOldStyle = r.EscapeOldStyle; + this->ImplicitDepends = r.ImplicitDepends; + + cmsys::auto_ptr<cmListFileBacktrace> + newBacktrace(new cmListFileBacktrace(*r.Backtrace)); + delete this->Backtrace; + this->Backtrace = newBacktrace.release(); + + return *this; +} + +//---------------------------------------------------------------------------- cmCustomCommand::cmCustomCommand(cmMakefile* mf, const std::vector<std::string>& outputs, const std::vector<std::string>& depends, diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h index dd92e34d7..e20d2bf40 100644 --- a/Source/cmCustomCommand.h +++ b/Source/cmCustomCommand.h @@ -27,6 +27,7 @@ public: /** Default and copy constructors for STL containers. */ cmCustomCommand(); cmCustomCommand(const cmCustomCommand& r); + cmCustomCommand& operator=(cmCustomCommand const& r); /** Main constructor specifies all information for the command. */ cmCustomCommand(cmMakefile* mf, diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index 43b7b8a60..a252a1ab7 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -193,17 +193,8 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, // Construct the name of the file as if it were in the current // include directory. Avoid using a leading "./". - tempPathStr = ""; - if((*i) == ".") - { - tempPathStr += current.FileName; - } - else - { - tempPathStr += *i; - tempPathStr+="/"; - tempPathStr+=current.FileName; - } + tempPathStr = + cmSystemTools::CollapseCombinedPath(*i, current.FileName); // Look for the file in this location. if(cmSystemTools::FileExists(tempPathStr.c_str(), true)) @@ -458,9 +449,8 @@ void cmDependsC::Scan(std::istream& is, const char* directory, // This was a double-quoted include with a relative path. We // must check for the file in the directory containing the // file we are scanning. - entry.QuotedLocation = directory; - entry.QuotedLocation += "/"; - entry.QuotedLocation += entry.FileName; + entry.QuotedLocation = + cmSystemTools::CollapseCombinedPath(directory, entry.FileName); } // Queue the file if it has not yet been encountered and it diff --git a/Source/cmDependsFortranLexer.cxx b/Source/cmDependsFortranLexer.cxx index b0d9a742d..924d9d2a9 100644 --- a/Source/cmDependsFortranLexer.cxx +++ b/Source/cmDependsFortranLexer.cxx @@ -913,9 +913,9 @@ extern int cmDependsFortran_yylex (yyscan_t yyscanner); */ YY_DECL { - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; #line 71 "cmDependsFortranLexer.in.l" @@ -966,7 +966,7 @@ YY_DECL yy_match: do { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1386,9 +1386,9 @@ ECHO; static int yy_get_next_buffer (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = yyg->yytext_ptr; - register int number_to_move, i; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = yyg->yytext_ptr; + int number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) @@ -1520,8 +1520,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner) static yy_state_type yy_get_previous_state (yyscan_t yyscanner) { - register yy_state_type yy_current_state; - register char *yy_cp; + yy_state_type yy_current_state; + char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_current_state = yyg->yy_start; @@ -1529,7 +1529,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1554,11 +1554,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) { - register int yy_is_jam; + int yy_is_jam; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ - register char *yy_cp = yyg->yy_c_buf_p; + char *yy_cp = yyg->yy_c_buf_p; - register YY_CHAR yy_c = 1; + YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1576,9 +1576,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner) return yy_is_jam ? 0 : yy_current_state; } - static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner) + static void yyunput (int c, char * yy_bp , yyscan_t yyscanner) { - register char *yy_cp; + char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_cp = yyg->yy_c_buf_p; @@ -1589,10 +1589,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ - register int number_to_move = yyg->yy_n_chars + 2; - register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + int number_to_move = yyg->yy_n_chars + 2; + char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - register char *source = + char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) @@ -2359,7 +2359,7 @@ int cmDependsFortran_yylex_destroy (yyscan_t yyscanner) #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) { - register int i; + int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } @@ -2368,7 +2368,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) { - register int n; + int n; for ( n = 0; s[n]; ++n ) ; diff --git a/Source/cmDependsFortranLexer.in.l b/Source/cmDependsFortranLexer.in.l index 40e80b719..01488024e 100644 --- a/Source/cmDependsFortranLexer.in.l +++ b/Source/cmDependsFortranLexer.in.l @@ -30,6 +30,7 @@ Run flex like this: Modify cmDependsFortranLexer.cxx: - remove TABs + - remove use of the 'register' storage class specifier - remove "yyscanner" argument from these methods: yy_fatal_error, cmDependsFortran_yyalloc, cmDependsFortran_yyrealloc, cmDependsFortran_yyfree - remove "yyscanner = NULL" from end of cmDependsFortran_yylex_destroy diff --git a/Source/cmDependsFortranParser.y b/Source/cmDependsFortranParser.y index 5681d698c..d814f3075 100644 --- a/Source/cmDependsFortranParser.y +++ b/Source/cmDependsFortranParser.y @@ -33,6 +33,7 @@ Run bison like this: Modify cmDependsFortranParser.cxx: - remove TABs + - remove use of the 'register' storage class specifier - Remove the yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ diff --git a/Source/cmDependsJavaLexer.cxx b/Source/cmDependsJavaLexer.cxx index 63cfebcd7..0af44b02e 100644 --- a/Source/cmDependsJavaLexer.cxx +++ b/Source/cmDependsJavaLexer.cxx @@ -904,9 +904,9 @@ extern int cmDependsJava_yylex (yyscan_t yyscanner); */ YY_DECL { - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; #line 88 "cmDependsJavaLexer.in.l" @@ -955,7 +955,7 @@ YY_DECL yy_match: do { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1604,9 +1604,9 @@ return 0; /* this should not happen but it silences a warning*/ static int yy_get_next_buffer (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = yyg->yytext_ptr; - register int number_to_move, i; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = yyg->yytext_ptr; + int number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) @@ -1730,15 +1730,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner) static yy_state_type yy_get_previous_state (yyscan_t yyscanner) { - register yy_state_type yy_current_state; - register char *yy_cp; + yy_state_type yy_current_state; + char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_current_state = yyg->yy_start; for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1763,11 +1763,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) { - register int yy_is_jam; + int yy_is_jam; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - register char *yy_cp = yyg->yy_c_buf_p; + char *yy_cp = yyg->yy_c_buf_p; - register YY_CHAR yy_c = 1; + YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -2481,7 +2481,7 @@ int cmDependsJava_yylex_destroy (yyscan_t yyscanner) #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) { - register int i; + int i; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; @@ -2491,7 +2491,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) { - register int n; + int n; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; for ( n = 0; s[n]; ++n ) ; diff --git a/Source/cmDependsJavaLexer.in.l b/Source/cmDependsJavaLexer.in.l index 9796ad52a..aa2f8a587 100644 --- a/Source/cmDependsJavaLexer.in.l +++ b/Source/cmDependsJavaLexer.in.l @@ -20,6 +20,7 @@ Run flex like this: Modify cmDependsJavaLexer.c: - remove TABs + - remove use of the 'register' storage class specifier - remove "yyscanner" argument from these methods: yy_fatal_error, cmDependsJava_yyalloc, cmDependsJava_yyrealloc, cmDependsJava_yyfree - remove all YY_BREAK lines occurring right after return statements diff --git a/Source/cmDependsJavaParser.cxx b/Source/cmDependsJavaParser.cxx index 7f7c385da..586c0debe 100644 --- a/Source/cmDependsJavaParser.cxx +++ b/Source/cmDependsJavaParser.cxx @@ -446,7 +446,7 @@ union yyalloc # define YYCOPY(To, From, Count) \ do \ { \ - register YYSIZE_T yyi; \ + YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ @@ -1821,7 +1821,7 @@ yystrlen (yystr) const char *yystr; # endif { - register const char *yys = yystr; + const char *yys = yystr; while (*yys++ != '\0') continue; @@ -1846,8 +1846,8 @@ yystpcpy (yydest, yysrc) const char *yysrc; # endif { - register char *yyd = yydest; - register const char *yys = yysrc; + char *yyd = yydest; + const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; @@ -1977,8 +1977,8 @@ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; - register int yystate; - register int yyn; + int yystate; + int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; @@ -1996,12 +1996,12 @@ int yynerrs; /* The state stack. */ short int yyssa[YYINITDEPTH]; short int *yyss = yyssa; - register short int *yyssp; + short int *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; - register YYSTYPE *yyvsp; + YYSTYPE *yyvsp; diff --git a/Source/cmDependsJavaParser.y b/Source/cmDependsJavaParser.y index 53210b8ca..944d4b5ce 100644 --- a/Source/cmDependsJavaParser.y +++ b/Source/cmDependsJavaParser.y @@ -20,6 +20,7 @@ Run bison like this: Modify cmDependsJavaParser.cxx: - remove TABs + - remove use of the 'register' storage class specifier - add __HP_aCC to the #if test for yyerrorlab warning suppression */ diff --git a/Source/cmDocumentCompileDefinitions.h b/Source/cmDocumentCompileDefinitions.h index ef3b3e715..d15bd6dca 100644 --- a/Source/cmDocumentCompileDefinitions.h +++ b/Source/cmDocumentCompileDefinitions.h @@ -23,7 +23,7 @@ "in a (configured) header file. Then report the limitation. " \ "Known limitations include:\n" \ " # - broken almost everywhere\n" \ - " ; - broken in VS IDE and Borland Makefiles\n" \ + " ; - broken in VS IDE 7.0 and Borland Makefiles\n" \ " , - broken in VS IDE\n" \ " % - broken in some cases in NMake\n" \ " & | - broken in some cases on MinGW\n" \ diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h index 6cc3f25ae..46cd77eae 100644 --- a/Source/cmDocumentGeneratorExpressions.h +++ b/Source/cmDocumentGeneratorExpressions.h @@ -13,7 +13,7 @@ #define cmDocumentGeneratorExpressions_h #define CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \ - "Generator expressions are evaluted during build system generation " \ + "Generator expressions are evaluated during build system generation " \ "to produce information specific to each build configuration. " \ "Valid expressions are:\n" \ " $<0:...> = empty string (ignores \"...\")\n" \ @@ -28,6 +28,8 @@ "strings which contain a ',' for example.\n" \ " $<SEMICOLON> = A literal ';'. Used to prevent " \ "list expansion on an argument with ';'.\n" \ + " $<JOIN:list,...> = joins the list with the content of " \ + "\"...\"\n" \ " $<TARGET_NAME:...> = Marks ... as being the name of a " \ "target. This is required if exporting targets to multiple " \ "dependent export sets. The '...' must be a literal name of a " \ @@ -38,6 +40,27 @@ "is exported using export(), or when the target is used by another " \ "target in the same buildsystem. Expands to the empty string " \ "otherwise.\n" \ + " $<C_COMPILER_ID> = The CMake-id of the C compiler " \ + "used.\n" \ + " $<C_COMPILER_ID:comp> = '1' if the CMake-id of the C " \ + "compiler matches comp, otherwise '0'.\n" \ + " $<CXX_COMPILER_ID> = The CMake-id of the CXX compiler " \ + "used.\n" \ + " $<CXX_COMPILER_ID:comp> = '1' if the CMake-id of the CXX " \ + "compiler matches comp, otherwise '0'.\n" \ + " $<VERSION_GREATER:v1,v2> = '1' if v1 is a version greater than " \ + "v2, else '0'.\n" \ + " $<VERSION_LESS:v1,v2> = '1' if v1 is a version less than v2, " \ + "else '0'.\n" \ + " $<VERSION_EQUAL:v1,v2> = '1' if v1 is the same version as v2, " \ + "else '0'.\n" \ + " $<C_COMPILER_VERSION> = The version of the C compiler used.\n" \ + " $<C_COMPILER_VERSION:ver> = '1' if the version of the C " \ + "compiler matches ver, otherwise '0'.\n" \ + " $<CXX_COMPILER_VERSION> = The version of the CXX compiler " \ + "used.\n" \ + " $<CXX_COMPILER_VERSION:ver> = '1' if the version of the CXX " \ + "compiler matches ver, otherwise '0'.\n" \ " $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \ " $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \ " $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \ diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 61f9f5a25..c4f6216b6 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -10,7 +10,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_AR", cmProperty::VARIABLE, "Name of archiving tool for static libraries.", - "This specifies name of the program that creates archive " + "This specifies the name of the program that creates archive " "or static libraries.",false, "Variables that Provide Information"); @@ -19,7 +19,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "The full path to the cmake executable.", "This is the full path to the CMake executable cmake which is " "useful from custom commands that want to use the cmake -E " - "option for portable system commands. " + "option for portable system commands. " "(e.g. /usr/local/bin/cmake", false, "Variables that Provide Information"); cm->DefineProperty @@ -27,14 +27,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "The path to the top level of the build tree.", "This is the full path to the top level of the current CMake " "build tree. For an in-source build, this would be the same " - "as CMAKE_SOURCE_DIR. ", false, + "as CMAKE_SOURCE_DIR.", false, "Variables that Provide Information"); cm->DefineProperty ("CMAKE_SOURCE_DIR", cmProperty::VARIABLE, "The path to the top level of the source tree.", "This is the full path to the top level of the current CMake " "source tree. For an in-source build, this would be the same " - "as CMAKE_BINARY_DIR. ", false, + "as CMAKE_BINARY_DIR.", false, "Variables that Provide Information"); cm->DefineProperty ("CMAKE_CURRENT_BINARY_DIR", cmProperty::VARIABLE, @@ -42,7 +42,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "This the full path to the build directory that is currently " "being processed by cmake. Each directory added by " "add_subdirectory will create a binary directory in the build " - "tree, and as it is being processed this variable will be set. " + "tree, and as it is being processed this variable will be set. " "For in-source builds this is the current source directory " "being processed.", false, "Variables that Provide Information"); @@ -100,7 +100,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_SCRIPT_MODE_FILE", cmProperty::VARIABLE, - "Full path to the -P script file currently being processed. ", + "Full path to the -P script file currently being processed.", "When run in -P script mode, CMake sets this variable to the full " "path of the script file. When run to configure a CMakeLists.txt " "file, this variable is not set.", false, @@ -108,14 +108,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_ARGC", cmProperty::VARIABLE, - "Number of command line arguments passed to CMake in script mode. ", + "Number of command line arguments passed to CMake in script mode.", "When run in -P script mode, CMake sets this variable to the number " - "of command line arguments. See also CMAKE_ARGV0, 1, 2 ... ", false, + "of command line arguments. See also CMAKE_ARGV0, 1, 2 ...", false, "Variables that Provide Information"); cm->DefineProperty ("CMAKE_ARGV0", cmProperty::VARIABLE, - "Command line argument passed to CMake in script mode. ", + "Command line argument passed to CMake in script mode.", "When run in -P script mode, CMake sets this variable to " "the first command line argument. It then also sets CMAKE_ARGV1, " "CMAKE_ARGV2, ... and so on, up to the number of command line arguments " @@ -129,11 +129,11 @@ void cmDocumentVariables::DefineVariables(cmake* cm) " needed to build the output of CMake. If the " "generator selected was Visual Studio 6, the " "CMAKE_BUILD_TOOL will be set to msdev, for " - "Unix makefiles it will be set to make or gmake, " + "Unix Makefiles it will be set to make or gmake, " "and for Visual Studio 7 it set to devenv. For " - "Nmake Makefiles the value is nmake. This can be " + "NMake Makefiles the value is nmake. This can be " "useful for adding special flags and commands based" - " on the final build environment. ", false, + " on the final build environment.", false, "Variables that Provide Information"); cm->DefineProperty ("CMAKE_CROSSCOMPILING", cmProperty::VARIABLE, @@ -152,7 +152,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_CACHE_MAJOR_VERSION", cmProperty::VARIABLE, "Major version of CMake used to create the CMakeCache.txt file", - "This is stores the major version of CMake used to " + "This stores the major version of CMake used to " "write a CMake cache file. It is only different when " "a different version of CMake is run on a previously " "created cache file.", false, @@ -160,7 +160,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_CACHE_MINOR_VERSION", cmProperty::VARIABLE, "Minor version of CMake used to create the CMakeCache.txt file", - "This is stores the minor version of CMake used to " + "This stores the minor version of CMake used to " "write a CMake cache file. It is only different when " "a different version of CMake is run on a previously " "created cache file.", false, @@ -169,7 +169,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_CACHE_PATCH_VERSION", cmProperty::VARIABLE, "Patch version of CMake used to create the CMakeCache.txt file", - "This is stores the patch version of CMake used to " + "This stores the patch version of CMake used to " "write a CMake cache file. It is only different when " "a different version of CMake is run on a previously " "created cache file.", false, @@ -270,12 +270,13 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_LINK_LIBRARY_SUFFIX", cmProperty::VARIABLE, "The suffix for libraries that you link to.", - "The suffix to use for the end of a library, .lib on Windows.",false, + "The suffix to use for the end of a library filename, .lib on Windows." + ,false, "Variables that Provide Information"); cm->DefineProperty ("CMAKE_EXECUTABLE_SUFFIX", cmProperty::VARIABLE, "The suffix for executables on this platform.", - "The suffix to use for the end of an executable if any, " + "The suffix to use for the end of an executable filename if any, " ".exe on Windows." "\n" "CMAKE_EXECUTABLE_SUFFIX_<LANG> overrides this for language <LANG>." @@ -344,11 +345,12 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_PARENT_LIST_FILE", cmProperty::VARIABLE, - "Full path to the parent listfile of the one currently being processed.", - "As CMake processes the listfiles in your project this " - "variable will always be set to the listfile that included " - "or somehow invoked the one currently being " - "processed. See also CMAKE_CURRENT_LIST_FILE.",false, + "Full path to the CMake file that included the current one.", + "While processing a CMake file loaded by include() or find_package() " + "this variable contains the full path to the file including it. " + "The top of the include stack is always the CMakeLists.txt for the " + "current directory. " + "See also CMAKE_CURRENT_LIST_FILE.",false, "Variables that Provide Information"); cm->DefineProperty @@ -391,7 +393,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_SOURCE_DIR", cmProperty::VARIABLE, "Source directory for project.", - "This is the top level source directory for the project. " + "This is the top level source directory for the project. " "It corresponds to the source directory given to " "cmake-gui or ccmake.",false, "Variables that Provide Information"); @@ -417,7 +419,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("PROJECT_NAME", cmProperty::VARIABLE, "Name of the project given to the project command.", "This is the name given to the most " - "recent PROJECT command. ",false, + "recent PROJECT command.",false, "Variables that Provide Information"); cm->DefineProperty ("PROJECT_SOURCE_DIR", cmProperty::VARIABLE, @@ -452,8 +454,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ,false, "Variables that Provide Information"); cm->DefineProperty ("CMAKE_IMPORT_LIBRARY_SUFFIX", cmProperty::VARIABLE, - "The suffix for import libraries that you link to.", - "The suffix to use for the end of an import library if used " + "The suffix for import libraries that you link to.", + "The suffix to use for the end of an import library filename if used " "on this platform." "\n" "CMAKE_IMPORT_LIBRARY_SUFFIX_<LANG> overrides this for language <LANG>." @@ -468,7 +470,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_SHARED_LIBRARY_SUFFIX", cmProperty::VARIABLE, "The suffix for shared libraries that you link to.", - "The suffix to use for the end of a shared library, .dll on Windows." + "The suffix to use for the end of a shared library filename, " + ".dll on Windows." "\n" "CMAKE_SHARED_LIBRARY_SUFFIX_<LANG> overrides this for language <LANG>." ,false, "Variables that Provide Information"); @@ -482,7 +485,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_SHARED_MODULE_SUFFIX", cmProperty::VARIABLE, "The suffix for shared libraries that you link to.", - "The suffix to use for the end of a loadable module on this platform" + "The suffix to use for the end of a loadable module filename " + "on this platform" "\n" "CMAKE_SHARED_MODULE_SUFFIX_<LANG> overrides this for language <LANG>." ,false, "Variables that Provide Information"); @@ -496,7 +500,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_STATIC_LIBRARY_SUFFIX", cmProperty::VARIABLE, "The suffix for static libraries that you link to.", - "The suffix to use for the end of a static library, .lib on Windows." + "The suffix to use for the end of a static library filename, " + ".lib on Windows." "\n" "CMAKE_STATIC_LIBRARY_SUFFIX_<LANG> overrides this for language <LANG>." ,false, "Variables that Provide Information"); @@ -509,6 +514,13 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "analysis of libraries linked by a target.", false, "Variables that Provide Information"); + cm->DefineProperty + ("CMAKE_MINIMUM_REQUIRED_VERSION", cmProperty::VARIABLE, + "Version specified to cmake_minimum_required command", + "Variable containing the VERSION component specified in the " + "cmake_minimum_required command.", + false, + "Variables that Provide Information"); // Variables defined by cmake, that change the behavior @@ -538,7 +550,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "By default, automoc behaves exactly as described in the documentation " "of the AUTOMOC target property. " "When set to TRUE, it accepts more input and tries to find the correct " - "input file for moc even if it differs from the documented behaviour. " + "input file for moc even if it differs from the documented behaviour. " "In this mode it e.g. also checks whether a header file is intended to " "be processed by moc when a \"foo.moc\" file has been included.\n" "Relaxed mode has to be enabled for KDE4 compatibility.", @@ -551,7 +563,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "If an install() command is used without the COMPONENT argument, " "these files will be grouped into a default component. The name of this " "default install component will be taken from this variable. " - "It defaults to \"Unspecified\". ", + "It defaults to \"Unspecified\".", false, "Variables That Change Behavior"); @@ -577,26 +589,37 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_CONFIGURATION_TYPES", cmProperty::VARIABLE, - "Specifies the available build types.", - "This specifies what build types will be available such as " - "Debug, Release, RelWithDebInfo etc. This has reasonable defaults " - "on most platforms. But can be extended to provide other " - "build types. See also CMAKE_BUILD_TYPE.", - false, + "Specifies the available build types on multi-config generators.", + "This specifies what build types (configurations) will be available " + "such as Debug, Release, RelWithDebInfo etc. " + "This has reasonable defaults on most platforms, " + "but can be extended to provide other build types. " + "See also CMAKE_BUILD_TYPE for details of managing configuration data, " + "and CMAKE_CFG_INTDIR." + ,false, "Variables That Change Behavior"); cm->DefineProperty ("CMAKE_BUILD_TYPE", cmProperty::VARIABLE, - "Specifies the build type for make based generators.", - "This specifies what build type will be built in this tree. " - " Possible values are empty, Debug, Release, RelWithDebInfo" - " and MinSizeRel. This variable is only supported for " - "make based generators. If this variable is supported, " - "then CMake will also provide initial values for the " - "variables with the name " - " CMAKE_C_FLAGS_[DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL]." - " For example, if CMAKE_BUILD_TYPE is Debug, then " - "CMAKE_C_FLAGS_DEBUG will be added to the CMAKE_C_FLAGS.",false, + "Specifies the build type on single-configuration generators.", + "This statically specifies what build type (configuration) " + "will be built in this build tree. Possible values are " + "empty, Debug, Release, RelWithDebInfo and MinSizeRel. " + "This variable is only meaningful to single-configuration generators " + "(such as make and Ninja) i.e. " + "those which choose a single configuration " + "when CMake runs to generate a build tree as opposed to " + "multi-configuration generators which offer selection of the build " + "configuration within the generated build environment. " + "There are many per-config properties and variables " + "(usually following clean SOME_VAR_<CONFIG> order conventions), " + "such as CMAKE_C_FLAGS_<CONFIG>, specified as uppercase: " + "CMAKE_C_FLAGS_[DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL]. " + "For example, in a build tree configured " + "to build type Debug, CMake will see to having " + "CMAKE_C_FLAGS_DEBUG settings get added to the CMAKE_C_FLAGS settings. " + "See also CMAKE_CONFIGURATION_TYPES." + ,false, "Variables That Change Behavior"); cm->DefineProperty @@ -616,32 +639,36 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_INSTALL_PREFIX", cmProperty::VARIABLE, "Install directory used by install.", "If \"make install\" is invoked or INSTALL is built" - ", this directory is pre-pended onto all install " + ", this directory is prepended onto all install " "directories. This variable defaults to /usr/local" " on UNIX and c:/Program Files on Windows.\n" "On UNIX one can use the DESTDIR mechanism in order" - " to relocate the whole installation. " + " to relocate the whole installation. " "DESTDIR means DESTination DIRectory. It is " "commonly used by makefile users " - "in order to install software at non-default location. " + "in order to install software at non-default location. " "It is usually invoked like this:\n" " make DESTDIR=/home/john install\n" "which will install the concerned software using the" - " installation prefix, e.g. \"/usr/local\" pre-pended with " + " installation prefix, e.g. \"/usr/local\" prepended with " "the DESTDIR value which finally gives \"/home/john/usr/local\".\n" "WARNING: DESTDIR may not be used on Windows because installation" " prefix usually contains a drive letter like in \"C:/Program Files\"" - " which cannot be pre-pended with some other prefix." + " which cannot be prepended with some other prefix." + "\n" + "The installation prefix is also added to CMAKE_SYSTEM_PREFIX_PATH " + "so that find_package, find_program, find_library, find_path, and " + "find_file will search the prefix for other software." ,false, "Variables That Change Behavior"); cm->DefineProperty ("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY", cmProperty::VARIABLE, "Don't make the install target depend on the all target.", - "By default, the \"install\" target depends on the \"all\" target. " + "By default, the \"install\" target depends on the \"all\" target. " "This has the effect, that when \"make install\" is invoked or INSTALL " "is built, first the \"all\" target is built, then the installation " - "starts. " + "starts. " "If CMAKE_SKIP_INSTALL_ALL_DEPENDENCY is set to TRUE, this dependency " "is not created, so the installation process will start immediately, " "independent from whether the project has been completely built or not." @@ -658,6 +685,23 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "Variables That Change Behavior"); cm->DefineProperty + ("CMAKE_WARN_DEPRECATED", cmProperty::VARIABLE, + "Whether to issue deprecation warnings for macros and functions.", + "If TRUE, this can be used by macros and functions to issue " + "deprecation warnings. This variable is FALSE by default.", + false, + "Variables That Change Behavior"); + + cm->DefineProperty + ("CMAKE_ERROR_DEPRECATED", cmProperty::VARIABLE, + "Whether to issue deprecation errors for macros and functions.", + "If TRUE, this can be used by macros and functions to issue " + "fatal errors when deprecated macros or functions are used. This " + "variable is FALSE by default.", + false, + "Variables That Change Behavior"); + + cm->DefineProperty ("CMAKE_PREFIX_PATH", cmProperty::VARIABLE, "Path used for searching by FIND_XXX(), with appropriate suffixes added.", "Specifies a path which will be used by the FIND_XXX() commands. It " @@ -709,7 +753,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "adds /bin to each of the directories in the path, FIND_LIBRARY() " "appends /lib to each of the directories, and FIND_PATH() and " "FIND_FILE() append /include . By default this contains the standard " - "directories for the current system. It is NOT intended " + "directories for the current system and the CMAKE_INSTALL_PREFIX. " + "It is NOT intended " "to be modified by the project, use CMAKE_PREFIX_PATH for this. See also " "CMAKE_SYSTEM_INCLUDE_PATH, CMAKE_SYSTEM_LIBRARY_PATH, " "CMAKE_SYSTEM_PROGRAM_PATH, and CMAKE_SYSTEM_IGNORE_PATH.", false, @@ -724,9 +769,9 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "directories contain incompatible but possibly linkable libraries. For " "example, on cross-compiled cluster environments, this allows a user to " "ignore directories containing libraries meant for the front-end " - "machine that modules like FindX11 (and others) would normally search. " + "machine that modules like FindX11 (and others) would normally search. " "By default this contains a list of directories containing incompatible " - "binaries for the host system. " + "binaries for the host system. " "See also CMAKE_SYSTEM_PREFIX_PATH, CMAKE_SYSTEM_LIBRARY_PATH, " "CMAKE_SYSTEM_INCLUDE_PATH, and CMAKE_SYSTEM_PROGRAM_PATH.", false, "Variables That Change Behavior"); @@ -740,11 +785,11 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "directories contain incompatible but possibly linkable libraries. For " "example, on cross-compiled cluster environments, this allows a user to " "ignore directories containing libraries meant for the front-end " - "machine that modules like FindX11 (and others) would normally search. " - "By default this is empty; it is intended to be set by the project. " + "machine that modules like FindX11 (and others) would normally search. " + "By default this is empty; it is intended to be set by the project. " "Note that CMAKE_IGNORE_PATH takes a list of directory names, NOT a " "list of prefixes. If you want to ignore paths under prefixes (bin, " - "include, lib, etc.), you'll need to specify them explicitly. " + "include, lib, etc.), you'll need to specify them explicitly. " "See also CMAKE_PREFIX_PATH, CMAKE_LIBRARY_PATH, CMAKE_INCLUDE_PATH, " "CMAKE_PROGRAM_PATH.", false, "Variables That Change Behavior"); @@ -791,8 +836,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "although that package is installed.\n" "This switch should be used during the initial CMake run. Otherwise if " "the package has already been found in a previous CMake run, the " - "variables which have been stored in the cache will still be there. " - "In the case it is recommended to remove the cache variables for " + "variables which have been stored in the cache will still be there. " + "In that case it is recommended to remove the cache variables for " "this package from the cache using the cache editor or cmake -U", false, "Variables That Change Behavior"); @@ -878,7 +923,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_COLOR_MAKEFILE", cmProperty::VARIABLE, "Enables color output when using the Makefile generator.", - "When enabled, the generated Makefiles will produce colored output. " + "When enabled, the generated Makefiles will produce colored output. " "Default is ON.",false, "Variables That Change Behavior"); @@ -888,7 +933,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) " an ABSOLUTE DESTINATION path.", "This variable is defined by CMake-generated cmake_install.cmake " "scripts." - " It can be used (read-only) by program or script that source those" + " It can be used (read-only) by programs or scripts that source those" " install scripts. This is used by some CPack generators (e.g. RPM).", false, "Variables That Change Behavior"); @@ -898,7 +943,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "Ask cmake_install.cmake script to warn each time a file with " "absolute INSTALL DESTINATION is encountered.", "This variable is used by CMake-generated cmake_install.cmake" - " scripts. If ones set this variable to ON while running the" + " scripts. If one sets this variable to ON while running the" " script, it may get warning messages from the script.", false, "Variables That Change Behavior"); @@ -909,7 +954,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "The fatal error is emitted before the installation of " "the offending file takes place." " This variable is used by CMake-generated cmake_install.cmake" - " scripts. If ones set this variable to ON while running the" + " scripts. If one sets this variable to ON while running the" " script, it may get fatal error messages from the script.",false, "Variables That Change Behavior"); @@ -918,9 +963,10 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "Enables tracing output for target properties.", "This variable can be populated with a list of properties to generate " "debug output for when evaluating target properties. Currently it can " - "only be used when evaluating the INCLUDE_DIRECTORIES target property. " - "In that case, it outputs a backtrace for each include directory in " - "the build. Default is unset.",false,"Variables That Change Behavior"); + "only be used when evaluating the INCLUDE_DIRECTORIES, " + "COMPILE_DEFINITIONS and COMPILE_OPTIONS target properties. " + "In that case, it outputs a backtrace for each entry in the target " + "property. Default is unset.", false, "Variables That Change Behavior"); // Variables defined by CMake that describe the system @@ -929,7 +975,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "Name of system cmake is compiling for.", "This variable is the composite of CMAKE_SYSTEM_NAME " "and CMAKE_SYSTEM_VERSION, like this " - "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_VERSION}. " + "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_VERSION}. " "If CMAKE_SYSTEM_VERSION is not set, then " "CMAKE_SYSTEM is the same as CMAKE_SYSTEM_NAME.",false, "Variables That Describe the System"); @@ -940,7 +986,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "which CMake is targeting. On systems that " "have the uname command, this variable is set " "to the output of uname -s. Linux, Windows, " - " and Darwin for Mac OSX are the values found " + " and Darwin for Mac OS X are the values found " " on the big three operating systems." ,false, "Variables That Describe the System"); cm->DefineProperty @@ -999,20 +1045,22 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("APPLE", cmProperty::VARIABLE, - "True if running on Mac OSX.", - "Set to true on Mac OSX.",false, + "True if running on Mac OS X.", + "Set to true on Mac OS X." + ,false, "Variables That Describe the System"); cm->DefineProperty ("BORLAND", cmProperty::VARIABLE, - "True if the borland compiler is being used.", + "True if the Borland compiler is being used.", "This is set to true if the Borland compiler is being used.",false, "Variables That Describe the System"); cm->DefineProperty ("CYGWIN", cmProperty::VARIABLE, - "True for cygwin.", - "Set to true when using CYGWIN.",false, + "True for Cygwin.", + "Set to true when using Cygwin." + ,false, "Variables That Describe the System"); cm->DefineProperty @@ -1111,8 +1159,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_HOST_APPLE", cmProperty::VARIABLE, - "True for Apple OSXoperating systems.", - "Set to true when the host system is Apple OSX.", + "True for Apple OS X operating systems.", + "Set to true when the host system is Apple OS X.", false, "Variables That Describe the System"); @@ -1126,7 +1174,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_HOST_WIN32", cmProperty::VARIABLE, "True on windows systems, including win64.", - "Set to true when the host system is Windows and on cygwin.",false, + "Set to true when the host system is Windows and on Cygwin." + ,false, "Variables That Describe the System"); cm->DefineProperty @@ -1147,6 +1196,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "The value must be an integer no less than 128.",false, "Variables That Describe the System"); + cm->DefineProperty + ("ENV", cmProperty::VARIABLE, + "Access environment variables.", + "Use the syntax $ENV{VAR} to read environment variable VAR. " + "See also the set() command to set ENV{VAR}." + ,false, + "Variables That Describe the System"); + // Variables that affect the building of object files and // targets. // @@ -1180,7 +1237,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_INSTALL_RPATH", cmProperty::VARIABLE, "The rpath to use for installed targets.", "A semicolon-separated list specifying the rpath " - "to use in installed targets (for platforms that support it). " + "to use in installed targets (for platforms that support it). " "This is used to initialize the target property " "INSTALL_RPATH for all targets.", false, @@ -1191,7 +1248,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "Add paths to linker search and installed rpath.", "CMAKE_INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to true " "will append directories in the linker search path and outside the " - "project to the INSTALL_RPATH. " + "project to the INSTALL_RPATH. " "This is used to initialize the target property " "INSTALL_RPATH_USE_LINK_PATH for all targets.", false, @@ -1199,7 +1256,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_INSTALL_NAME_DIR", cmProperty::VARIABLE, - "Mac OSX directory name for installed targets.", + "Mac OS X directory name for installed targets.", "CMAKE_INSTALL_NAME_DIR is used to initialize the " "INSTALL_NAME_DIR property on all targets. See that target " "property for more information.", @@ -1210,7 +1267,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_Fortran_FORMAT", cmProperty::VARIABLE, "Set to FIXED or FREE to indicate the Fortran source layout.", "This variable is used to initialize the Fortran_FORMAT " - "property on all the targets. " + "property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1219,7 +1276,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_Fortran_MODULE_DIRECTORY", cmProperty::VARIABLE, "Fortran module output directory.", "This variable is used to initialize the " - "Fortran_MODULE_DIRECTORY property on all the targets. " + "Fortran_MODULE_DIRECTORY property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1228,7 +1285,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_LIBRARY_OUTPUT_DIRECTORY", cmProperty::VARIABLE, "Where to put all the LIBRARY targets when built.", "This variable is used to initialize the " - "LIBRARY_OUTPUT_DIRECTORY property on all the targets. " + "LIBRARY_OUTPUT_DIRECTORY property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1237,7 +1294,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_ARCHIVE_OUTPUT_DIRECTORY", cmProperty::VARIABLE, "Where to put all the ARCHIVE targets when built.", "This variable is used to initialize the " - "ARCHIVE_OUTPUT_DIRECTORY property on all the targets. " + "ARCHIVE_OUTPUT_DIRECTORY property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1246,16 +1303,16 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_RUNTIME_OUTPUT_DIRECTORY", cmProperty::VARIABLE, "Where to put all the RUNTIME targets when built.", "This variable is used to initialize the " - "RUNTIME_OUTPUT_DIRECTORY property on all the targets. " + "RUNTIME_OUTPUT_DIRECTORY property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); cm->DefineProperty ("CMAKE_PDB_OUTPUT_DIRECTORY", cmProperty::VARIABLE, - "Where to put all the MS debug symbol files.", + "Where to put all the MS debug symbol files from linker.", "This variable is used to initialize the " - "PDB_OUTPUT_DIRECTORY property on all the targets. " + "PDB_OUTPUT_DIRECTORY property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1273,7 +1330,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_AUTOMOC", cmProperty::VARIABLE, "Whether to handle moc automatically for Qt targets.", "This variable is used to initialize the " - "AUTOMOC property on all the targets. " + "AUTOMOC property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1282,7 +1339,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_AUTOMOC_MOC_OPTIONS", cmProperty::VARIABLE, "Additional options for moc when using automoc (see CMAKE_AUTOMOC).", "This variable is used to initialize the " - "AUTOMOC_MOC_OPTIONS property on all the targets. " + "AUTOMOC_MOC_OPTIONS property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1359,45 +1416,91 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_EXE_LINKER_FLAGS", cmProperty::VARIABLE, - "Linker flags used to create executables.", - "Flags used by the linker when creating an executable.",false, + "Linker flags to be used to create executables.", + "These flags will be used by the linker when creating an executable." + ,false, "Variables that Control the Build"); cm->DefineProperty - ("CMAKE_EXE_LINKER_FLAGS_[CMAKE_BUILD_TYPE]", cmProperty::VARIABLE, - "Flag used when linking an executable.", + ("CMAKE_EXE_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE, + "Flags to be used when linking an executable.", "Same as CMAKE_C_FLAGS_* but used by the linker " "when creating executables.",false, "Variables that Control the Build"); + + cm->DefineProperty + ("CMAKE_MODULE_LINKER_FLAGS", cmProperty::VARIABLE, + "Linker flags to be used to create modules.", + "These flags will be used by the linker when creating a module." + ,false, + "Variables that Control the Build"); + + cm->DefineProperty + ("CMAKE_MODULE_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE, + "Flags to be used when linking a module.", + "Same as CMAKE_C_FLAGS_* but used by the linker " + "when creating modules.",false, + "Variables that Control the Build"); + + cm->DefineProperty + ("CMAKE_SHARED_LINKER_FLAGS", cmProperty::VARIABLE, + "Linker flags to be used to create shared libraries.", + "These flags will be used by the linker when creating a shared library." + ,false, + "Variables that Control the Build"); + + cm->DefineProperty + ("CMAKE_SHARED_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE, + "Flags to be used when linking a shared library.", + "Same as CMAKE_C_FLAGS_* but used by the linker " + "when creating shared libraries.",false, + "Variables that Control the Build"); + + cm->DefineProperty + ("CMAKE_STATIC_LINKER_FLAGS", cmProperty::VARIABLE, + "Linker flags to be used to create static libraries.", + "These flags will be used by the linker when creating a static library." + ,false, + "Variables that Control the Build"); + + cm->DefineProperty + ("CMAKE_STATIC_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE, + "Flags to be used when linking a static library.", + "Same as CMAKE_C_FLAGS_* but used by the linker " + "when creating static libraries.",false, + "Variables that Control the Build"); + cm->DefineProperty ("CMAKE_LIBRARY_PATH_FLAG", cmProperty::VARIABLE, - "The flag used to add a library search path to a compiler.", - "The flag used to specify a library directory to the compiler. " + "The flag to be used to add a library search path to a compiler.", + "The flag will be used to specify a library directory to the compiler. " "On most compilers this is \"-L\".",false, "Variables that Control the Build"); cm->DefineProperty ("CMAKE_LINK_DEF_FILE_FLAG ", cmProperty::VARIABLE, - "Linker flag used to specify a .def file for dll creation.", - "The flag used to add a .def file when creating " - "a dll on Windows, this is only defined on Windows.",false, + "Linker flag to be used to specify a .def file for dll creation.", + "The flag will be used to add a .def file when creating " + "a dll on Windows; this is only defined on Windows." + ,false, "Variables that Control the Build"); cm->DefineProperty ("CMAKE_LINK_LIBRARY_FLAG", cmProperty::VARIABLE, - "Flag used to link a library into an executable.", - "The flag used to specify a library to link to an executable. " + "Flag to be used to link a library into an executable.", + "The flag will be used to specify a library to link to an executable. " "On most compilers this is \"-l\".",false, "Variables that Control the Build"); cm->DefineProperty ("CMAKE_LINK_LIBRARY_FILE_FLAG", cmProperty::VARIABLE, - "Flag used to link a library specified by a path to its file.", - "The flag used before a library file path is given to the linker. " + "Flag to be used to link a library specified by a path to its file.", + "The flag will be used before a library file path is given to the " + "linker. " "This is needed only on very few platforms.", false, "Variables that Control the Build"); cm->DefineProperty ("CMAKE_USE_RELATIVE_PATHS", cmProperty::VARIABLE, "Use relative paths (May not work!).", - "If this is set to TRUE, then the CMake will use " - "relative paths between the source and binary tree. " + "If this is set to TRUE, then CMake will use " + "relative paths between the source and binary tree. " "This option does not work for more complicated " "projects, and relative paths are used when possible. " "In general, it is not possible to move CMake generated" @@ -1431,7 +1534,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_LINK_INTERFACE_LIBRARIES", cmProperty::VARIABLE, "Default value for LINK_INTERFACE_LIBRARIES of targets.", "This variable is used to initialize the " - "LINK_INTERFACE_LIBRARIES property on all the targets. " + "LINK_INTERFACE_LIBRARIES property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1439,7 +1542,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_WIN32_EXECUTABLE", cmProperty::VARIABLE, "Default value for WIN32_EXECUTABLE of targets.", "This variable is used to initialize the " - "WIN32_EXECUTABLE property on all the targets. " + "WIN32_EXECUTABLE property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1447,7 +1550,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_MACOSX_BUNDLE", cmProperty::VARIABLE, "Default value for MACOSX_BUNDLE of targets.", "This variable is used to initialize the " - "MACOSX_BUNDLE property on all the targets. " + "MACOSX_BUNDLE property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1455,7 +1558,23 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_POSITION_INDEPENDENT_CODE", cmProperty::VARIABLE, "Default value for POSITION_INDEPENDENT_CODE of targets.", "This variable is used to initialize the " - "POSITION_INDEPENDENT_CODE property on all the targets. " + "POSITION_INDEPENDENT_CODE property on all the targets. " + "See that target property for additional information.", + false, + "Variables that Control the Build"); + cm->DefineProperty + ("CMAKE_<LANG>_VISIBILITY_PRESET", cmProperty::VARIABLE, + "Default value for <LANG>_VISIBILITY_PRESET of targets.", + "This variable is used to initialize the " + "<LANG>_VISIBILITY_PRESET property on all the targets. " + "See that target property for additional information.", + false, + "Variables that Control the Build"); + cm->DefineProperty + ("CMAKE_VISIBILITY_INLINES_HIDDEN", cmProperty::VARIABLE, + "Default value for VISIBILITY_INLINES_HIDDEN of targets.", + "This variable is used to initialize the " + "VISIBILITY_INLINES_HIDDEN property on all the targets. " "See that target property for additional information.", false, "Variables that Control the Build"); @@ -1476,7 +1595,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_<LANG>_COMPILER", cmProperty::VARIABLE, "The full path to the compiler for LANG.", - "This is the command that will be used as the <LANG> compiler. " + "This is the command that will be used as the <LANG> compiler. " "Once set, you can not change this variable.",false, "Variables for Languages"); @@ -1552,7 +1671,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_COMPILER_IS_GNU<LANG>", cmProperty::VARIABLE, "True if the compiler is GNU.", "If the selected <LANG> compiler is the GNU " - "compiler then this is TRUE, if not it is FALSE. " + "compiler then this is TRUE, if not it is FALSE. " "Unlike the other per-language variables, this uses the GNU syntax for " "identifying languages instead of the CMake syntax. Recognized values of " "the <LANG> suffix are:\n" @@ -1563,6 +1682,12 @@ void cmDocumentVariables::DefineVariables(cmake* cm) "Variables for Languages"); cm->DefineProperty + ("CMAKE_<LANG>_FLAGS", cmProperty::VARIABLE, + "Flags for all build types.", + "<LANG> flags used regardless of the value of CMAKE_BUILD_TYPE.",false, + "Variables for Languages"); + + cm->DefineProperty ("CMAKE_<LANG>_FLAGS_DEBUG", cmProperty::VARIABLE, "Flags for Debug build type or configuration.", "<LANG> flags used when CMAKE_BUILD_TYPE is Debug.",false, @@ -1584,7 +1709,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_<LANG>_FLAGS_RELWITHDEBINFO", cmProperty::VARIABLE, "Flags for RelWithDebInfo type or configuration.", - "<LANG> flags used when CMAKE_BUILD_TYPE is RelWithDebInfo. " + "<LANG> flags used when CMAKE_BUILD_TYPE is RelWithDebInfo. " "Short for Release With Debug Information.",false, "Variables for Languages"); @@ -1592,7 +1717,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_<LANG>_COMPILE_OBJECT", cmProperty::VARIABLE, "Rule variable to compile a single object file.", "This is a rule variable that tells CMake how to " - "compile a single object file for for the language <LANG>.",false, + "compile a single object file for the language <LANG>." + ,false, "Variables for Languages"); cm->DefineProperty @@ -1647,7 +1773,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_<LANG>_IGNORE_EXTENSIONS", cmProperty::VARIABLE, "File extensions that should be ignored by the build.", "This is a list of file extensions that may be " - "part of a project for a given language but are not compiled. ",false, + "part of a project for a given language but are not compiled.",false, "Variables for Languages"); cm->DefineProperty @@ -1728,8 +1854,9 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cm->DefineProperty ("CMAKE_<LANG>_LINK_EXECUTABLE ", cmProperty::VARIABLE, - "Rule variable to link and executable.", - "Rule variable to link and executable for the given language.",false, + "Rule variable to link an executable.", + "Rule variable to link an executable for the given language." + ,false, "Variables for Languages"); cm->DefineProperty @@ -1743,7 +1870,9 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_<LANG>_SOURCE_FILE_EXTENSIONS", cmProperty::VARIABLE, "Extensions of source files for the given language.", "This is the list of extensions for a " - "given languages source files.",false,"Variables for Languages"); + "given language's source files." + ,false, + "Variables for Languages"); cm->DefineProperty( "CMAKE_<LANG>_COMPILER_LOADED", cmProperty::VARIABLE, @@ -1799,8 +1928,6 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_<LANG>_CREATE_PREPROCESSED_SOURCE", cmProperty::VARIABLE,0,0); - cm->DefineProperty("CMAKE_<LANG>_FLAGS", - cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_<LANG>_FLAGS_DEBUG_INIT", cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_<LANG>_FLAGS_INIT", diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index debde3be9..4edacbb1a 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -53,7 +53,7 @@ static const char *cmModulesDocumentationDescription[][3] = "This is the documentation for the modules and scripts coming with CMake. " "Using these modules you can check the computer system for " "installed software packages, features of the compiler and the " - "existance of headers to name just a few.", 0}, + "existence of headers to name just a few.", 0}, {0,0,0} }; @@ -67,7 +67,7 @@ static const char *cmCustomModulesDocumentationDescription[][3] = "This is the documentation for additional modules and scripts for CMake. " "Using these modules you can check the computer system for " "installed software packages, features of the compiler and the " - "existance of headers to name just a few.", 0}, + "existence of headers to name just a few.", 0}, {0,0,0} }; diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 1158fc0c0..30de9a8a6 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -19,7 +19,12 @@ #include <cmsys/CPU.h> // Include the ELF format information system header. -#include <elf.h> +#if defined(__OpenBSD__) +# include <stdint.h> +# include <elf_abi.h> +#else +# include <elf.h> +#endif #if defined(__sun) # include <sys/link.h> // For dynamic section information #endif diff --git a/Source/cmEnableLanguageCommand.h b/Source/cmEnableLanguageCommand.h index ee963f920..747448b3e 100644 --- a/Source/cmEnableLanguageCommand.h +++ b/Source/cmEnableLanguageCommand.h @@ -59,18 +59,21 @@ public: virtual const char* GetFullDocumentation() const { return - " enable_language(languageName [OPTIONAL] )\n" + " enable_language(<lang> [OPTIONAL] )\n" "This command enables support for the named language in CMake. " "This is the same as the project command but does not create " "any of the extra variables that are created by the project command. " "Example languages are CXX, C, Fortran. " - "If OPTIONAL is used, use the CMAKE_<languageName>_COMPILER_WORKS " - "variable to check whether the language has been enabled successfully." "\n" - "This command must be called on file scope (not inside a function) and " - "the language enabled can only be used in the calling project or its " - "subdirectories added by add_subdirectory(). Also note that at present, " - "the OPTIONAL argument does not work."; + "This command must be called in file scope, not in a function call. " + "Furthermore, it must be called in the highest directory common to " + "all targets using the named language directly for compiling sources " + "or indirectly through link dependencies. " + "It is simplest to enable all needed languages in the top-level " + "directory of a project." + "\n" + "The OPTIONAL keyword is a placeholder for future implementation " + "and does not currently work."; } cmTypeMacro(cmEnableLanguageCommand, cmCommand); diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 7147f86be..cdc3316c4 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -30,7 +30,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) tei = this->Exports->begin(); tei != this->Exports->end(); ++tei) { - expectedTargets += sep + this->Namespace + (*tei)->GetName(); + expectedTargets += sep + this->Namespace + (*tei)->GetExportName(); sep = " "; cmTarget* te = *tei; if(this->ExportedTargets.insert(te).second) @@ -72,8 +72,20 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te, cmGeneratorExpression::BuildInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", te, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", te, properties); + const bool newCMP0022Behavior = + te->GetPolicyStatusCMP0022() != cmPolicies::WARN + && te->GetPolicyStatusCMP0022() != cmPolicies::OLD; + if (newCMP0022Behavior) + { + this->PopulateInterfaceLinkLibrariesProperty(te, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); + } this->PopulateCompatibleInterfaceProperties(te, properties); this->GenerateInterfaceProperties(te, os, properties); @@ -143,7 +155,7 @@ cmExportBuildFileGenerator std::string prop = "IMPORTED_LOCATION"; prop += suffix; std::string value; - if(target->IsFrameworkOnApple() || target->IsAppBundleOnApple()) + if(target->IsAppBundleOnApple()) { value = target->GetFullPath(config, false); } @@ -189,7 +201,7 @@ cmExportBuildFileGenerator::HandleMissingTarget( // Assume the target will be exported by another command. // Append it with the export namespace. link_libs += this->Namespace; - link_libs += dependee->GetName(); + link_libs += dependee->GetExportName(); } //---------------------------------------------------------------------------- @@ -211,3 +223,19 @@ cmExportBuildFileGenerator << "consider using the APPEND option with multiple separate calls."; this->ExportCommand->ErrorMessage = e.str(); } + +std::string +cmExportBuildFileGenerator::InstallNameDir(cmTarget* target, + const std::string& config) +{ + std::string install_name_dir; + + cmMakefile* mf = target->GetMakefile(); + if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + install_name_dir = + target->GetInstallNameDirForBuildTree(config.c_str()); + } + + return install_name_dir; +} diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 5e1be1648..3ffdf8b13 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -61,6 +61,8 @@ protected: cmTarget* target, ImportPropertyMap& properties); + std::string InstallNameDir(cmTarget* target, const std::string& config); + std::vector<cmTarget*> const* Exports; cmExportCommand* ExportCommand; }; diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 1cc17545a..f059ceba6 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -30,6 +30,7 @@ cmExportCommand::cmExportCommand() ,Append(&Helper, "APPEND", &ArgumentGroup) ,Namespace(&Helper, "NAMESPACE", &ArgumentGroup) ,Filename(&Helper, "FILE", &ArgumentGroup) +,ExportOld(&Helper, "EXPORT_LINK_INTERFACE_LIBRARIES", &ArgumentGroup) { // at first TARGETS this->Targets.Follows(0); @@ -113,6 +114,15 @@ bool cmExportCommand currentTarget != this->Targets.GetVector().end(); ++currentTarget) { + if (this->Makefile->IsAlias(currentTarget->c_str())) + { + cmOStringStream e; + e << "given ALIAS target \"" << *currentTarget + << "\" which may not be exported."; + this->SetError(e.str().c_str()); + return false; + } + if(cmTarget* target = this->Makefile->GetLocalGenerator()-> GetGlobalGenerator()->FindTarget(0, currentTarget->c_str())) @@ -158,6 +168,7 @@ bool cmExportCommand ebfg.SetAppendMode(this->Append.IsEnabled()); ebfg.SetExports(&targets); ebfg.SetCommand(this); + ebfg.SetExportOld(this->ExportOld.IsEnabled()); // Compute the set of configurations exported. std::vector<std::string> configurationTypes; @@ -210,7 +221,7 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args) else { cmOStringStream e; - e << "PACKAGE given unknown argumsnt: " << args[i]; + e << "PACKAGE given unknown argument: " << args[i]; this->SetError(e.str().c_str()); return false; } diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h index ae67b4762..87c345284 100644 --- a/Source/cmExportCommand.h +++ b/Source/cmExportCommand.h @@ -63,7 +63,7 @@ public: { return " export(TARGETS [target1 [target2 [...]]] [NAMESPACE <namespace>]\n" - " [APPEND] FILE <filename>)\n" + " [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES])\n" "Create a file <filename> that may be included by outside projects to " "import targets from the current project's build tree. " "This is useful during cross-compiling to build utility executables " @@ -73,6 +73,10 @@ public: "prepended to all target names written to the file. " "If the APPEND option is given the generated code will be appended " "to the file instead of overwriting it. " + "The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if present, causes the " + "contents of the properties matching " + "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? to be exported, when " + "policy CMP0022 is NEW. " "If a library target is included in the export but " "a target to which it links is not included the behavior is " "unspecified." @@ -104,6 +108,7 @@ private: cmCAEnabler Append; cmCAString Namespace; cmCAString Filename; + cmCAEnabler ExportOld; friend class cmExportBuildFileGenerator; std::string ErrorMessage; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 27ec56beb..14be5cd47 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -30,6 +30,7 @@ cmExportFileGenerator::cmExportFileGenerator() { this->AppendMode = false; + this->ExportOld = false; } //---------------------------------------------------------------------------- @@ -168,6 +169,43 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, } } +void cmExportFileGenerator::GenerateRequiredCMakeVersion(std::ostream& os, + const char *versionString) +{ + os << "if(CMAKE_VERSION VERSION_LESS " << versionString << ")\n" + " message(FATAL_ERROR \"This file relies on consumers using " + "CMake " << versionString << " or greater.\")\n" + "endif()\n\n"; +} + +//---------------------------------------------------------------------------- +bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty( + cmTarget *target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap &properties, + std::vector<std::string> &missingTargets) +{ + if(!target->IsLinkable()) + { + return false; + } + const char *input = target->GetProperty("INTERFACE_LINK_LIBRARIES"); + if (input) + { + std::string prepro = cmGeneratorExpression::Preprocess(input, + preprocessRule); + if (!prepro.empty()) + { + this->ResolveTargetsInGeneratorExpressions(prepro, target, + missingTargets, + ReplaceFreeTargets); + properties["INTERFACE_LINK_LIBRARIES"] = prepro; + return true; + } + } + return false; +} + //---------------------------------------------------------------------------- static bool isSubDirectory(const char* a, const char* b) { @@ -243,28 +281,55 @@ static bool checkInterfaceDirs(const std::string &prepro, //---------------------------------------------------------------------------- void cmExportFileGenerator::PopulateIncludeDirectoriesInterface( - cmTarget *target, + cmTargetExport *tei, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap &properties, std::vector<std::string> &missingTargets) { + cmTarget *target = tei->Target; assert(preprocessRule == cmGeneratorExpression::InstallInterface); const char *propName = "INTERFACE_INCLUDE_DIRECTORIES"; const char *input = target->GetProperty(propName); - if (!input) + + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + std::string dirs = tei->InterfaceIncludeDirectories; + this->ReplaceInstallPrefix(dirs); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs); + std::string exportDirs = cge->Evaluate(target->GetMakefile(), 0, + false, target); + + if (cge->GetHadContextSensitiveCondition()) { + cmMakefile* mf = target->GetMakefile(); + cmOStringStream e; + e << "Target \"" << target->GetName() << "\" is installed with " + "INCLUDES DESTINATION set to a context sensitive path. Paths which " + "depend on the configuration, policy values or the link interface are " + "not supported. Consider using target_include_directories instead."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } - if (!*input) + + if (!input && exportDirs.empty()) + { + return; + } + if ((input && !*input) && exportDirs.empty()) { // Set to empty properties[propName] = ""; return; } - std::string prepro = cmGeneratorExpression::Preprocess(input, - preprocessRule); + std::string includes = (input?input:""); + const char* sep = input ? ";" : ""; + includes += sep + exportDirs; + std::string prepro = cmGeneratorExpression::Preprocess(includes, + preprocessRule, + true); if (!prepro.empty()) { this->ResolveTargetsInGeneratorExpressions(prepro, target, @@ -315,6 +380,16 @@ void getCompatibleInterfaceProperties(cmTarget *target, { cmComputeLinkInformation *info = target->GetLinkInformation(config); + if (!info) + { + cmMakefile* mf = target->GetMakefile(); + cmOStringStream e; + e << "Exporting the target \"" << target->GetName() << "\" is not " + "allowed since its linker language cannot be determined"; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); for(cmComputeLinkInformation::ItemVector::const_iterator li = @@ -376,7 +451,7 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target, if (!properties.empty()) { std::string targetName = this->Namespace; - targetName += target->GetName(); + targetName += target->GetExportName(); os << "set_target_properties(" << targetName << " PROPERTIES\n"; for(ImportPropertyMap::const_iterator pi = properties.begin(); pi != properties.end(); ++pi) @@ -407,7 +482,7 @@ cmExportFileGenerator::AddTargetNamespace(std::string &input, } if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) { - input = this->Namespace + input; + input = this->Namespace + tgt->GetExportName(); } else { @@ -560,6 +635,7 @@ cmExportFileGenerator if (iface->ImplementationIsInterface) { + // Policy CMP0022 must not be NEW. this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_INTERFACE_LIBRARIES", iface->Libraries, properties, missingTargets); @@ -583,6 +659,22 @@ cmExportFileGenerator return; } + const bool newCMP0022Behavior = + target->GetPolicyStatusCMP0022() != cmPolicies::WARN + && target->GetPolicyStatusCMP0022() != cmPolicies::OLD; + + if(newCMP0022Behavior && !this->ExportOld) + { + cmMakefile *mf = target->GetMakefile(); + cmOStringStream e; + e << "Target \"" << target->GetName() << "\" has policy CMP0022 enabled, " + "but also has old-style LINK_INTERFACE_LIBRARIES properties " + "populated, but it was exported without the " + "EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties"; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + if (!*propContent) { properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = ""; @@ -624,8 +716,12 @@ cmExportFileGenerator std::string value; if(target->HasSOName(config)) { + if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + value = this->InstallNameDir(target, config); + } prop = "IMPORTED_SONAME"; - value = target->GetSOName(config); + value += target->GetSOName(config); } else { @@ -738,7 +834,9 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os) void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os, const std::string &expectedTargets) { - os << "set(_targetsDefined)\n" + os << "# Protect against multiple inclusion, which would fail when already " + "imported targets are added once more.\n" + "set(_targetsDefined)\n" "set(_targetsNotDefined)\n" "set(_expectedTargets)\n" "foreach(_expectedTarget " << expectedTargets << ")\n" @@ -772,7 +870,8 @@ cmExportFileGenerator { // Construct the imported target name. std::string targetName = this->Namespace; - targetName += target->GetName(); + + targetName += target->GetExportName(); // Create the imported target. os << "# Create imported target " << targetName << "\n"; @@ -835,7 +934,8 @@ cmExportFileGenerator { // Construct the imported target name. std::string targetName = this->Namespace; - targetName += target->GetName(); + + targetName += target->GetExportName(); // Set the import properties. os << "# Import target \"" << targetName << "\" for configuration \"" @@ -954,7 +1054,7 @@ cmExportFileGenerator { // Construct the imported target name. std::string targetName = this->Namespace; - targetName += target->GetName(); + targetName += target->GetExportName(); os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n" "list(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " "; diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 9f958a234..9628b9681 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -15,6 +15,8 @@ #include "cmCommand.h" #include "cmGeneratorExpression.h" +class cmTargetExport; + /** \class cmExportFileGenerator * \brief Generate a file exporting targets from a build or install tree. * @@ -35,6 +37,8 @@ public: /** Set the namespace in which to place exported target names. */ void SetNamespace(const char* ns) { this->Namespace = ns; } + void SetExportOld(bool exportOld) { this->ExportOld = exportOld; } + /** Add a configuration to be exported. */ void AddConfiguration(const char* config); @@ -101,6 +105,10 @@ protected: cmGeneratorExpression::PreprocessContext, ImportPropertyMap &properties, std::vector<std::string> &missingTargets); + bool PopulateInterfaceLinkLibrariesProperty(cmTarget *target, + cmGeneratorExpression::PreprocessContext, + ImportPropertyMap &properties, + std::vector<std::string> &missingTargets); void PopulateInterfaceProperty(const char *propName, cmTarget *target, ImportPropertyMap &properties); void PopulateCompatibleInterfaceProperties(cmTarget *target, @@ -108,7 +116,7 @@ protected: void GenerateInterfaceProperties(cmTarget *target, std::ostream& os, const ImportPropertyMap &properties); void PopulateIncludeDirectoriesInterface( - cmTarget *target, + cmTargetExport *target, cmGeneratorExpression::PreprocessContext preprocessRule, ImportPropertyMap &properties, std::vector<std::string> &missingTargets); @@ -128,9 +136,14 @@ protected: std::vector<std::string> &missingTargets, FreeTargetsReplace replace = NoReplaceFreeTargets); + void GenerateRequiredCMakeVersion(std::ostream& os, + const char *versionString); + // The namespace in which the exports are placed in the generated file. std::string Namespace; + bool ExportOld; + // The set of configurations to export. std::vector<std::string> Configurations; @@ -159,6 +172,9 @@ private: std::vector<std::string> &missingTargets); virtual void ReplaceInstallPrefix(std::string &input); + + virtual std::string InstallNameDir(cmTarget* target, + const std::string& config) = 0; }; #endif diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index ad12b5a13..c8b4a7985 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -39,7 +39,7 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob() //---------------------------------------------------------------------------- bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) { - std::vector<cmTarget*> allTargets; + std::vector<cmTargetExport*> allTargets; { std::string expectedTargets; std::string sep; @@ -47,12 +47,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) tei = this->IEGen->GetExportSet()->GetTargetExports()->begin(); tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei) { - expectedTargets += sep + this->Namespace + (*tei)->Target->GetName(); + expectedTargets += sep + this->Namespace + (*tei)->Target->GetExportName(); sep = " "; - cmTargetExport const* te = *tei; + cmTargetExport * te = *tei; if(this->ExportedTargets.insert(te->Target).second) { - allTargets.push_back(te->Target); + allTargets.push_back(te); } else { @@ -113,23 +113,46 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) std::vector<std::string> missingTargets; + bool require2_8_12 = false; // Create all the imported targets. - for(std::vector<cmTarget*>::const_iterator + for(std::vector<cmTargetExport*>::const_iterator tei = allTargets.begin(); tei != allTargets.end(); ++tei) { - cmTarget* te = *tei; + cmTarget* te = (*tei)->Target; this->GenerateImportTargetCode(os, te); ImportPropertyMap properties; - this->PopulateIncludeDirectoriesInterface(te, + this->PopulateIncludeDirectoriesInterface(*tei, + cmGeneratorExpression::InstallInterface, + properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", + te, cmGeneratorExpression::InstallInterface, properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te, cmGeneratorExpression::InstallInterface, properties, missingTargets); + this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", + te, + cmGeneratorExpression::InstallInterface, + properties, missingTargets); + + const bool newCMP0022Behavior = + te->GetPolicyStatusCMP0022() != cmPolicies::WARN + && te->GetPolicyStatusCMP0022() != cmPolicies::OLD; + if (newCMP0022Behavior) + { + if (this->PopulateInterfaceLinkLibrariesProperty(te, + cmGeneratorExpression::InstallInterface, + properties, missingTargets) + && !this->ExportOld) + { + require2_8_12 = true; + } + } this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", te, properties); this->PopulateCompatibleInterfaceProperties(te, properties); @@ -137,6 +160,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateInterfaceProperties(te, os, properties); } + if (require2_8_12) + { + this->GenerateRequiredCMakeVersion(os, "2.8.12"); + } // Now load per-configuration properties for them. os << "# Load information for each installed configuration.\n" @@ -351,27 +378,7 @@ cmExportInstallFileGenerator prop += suffix; // Append the installed file name. - if(target->IsFrameworkOnApple()) - { - value += itgen->GetInstallFilename(target, config); - value += ".framework/"; - value += itgen->GetInstallFilename(target, config); - } - else if(target->IsCFBundleOnApple()) - { - const char *ext = target->GetProperty("BUNDLE_EXTENSION"); - if (!ext) - { - ext = "bundle"; - } - - value += itgen->GetInstallFilename(target, config); - value += "."; - value += ext; - value += "/"; - value += itgen->GetInstallFilename(target, config); - } - else if(target->IsAppBundleOnApple()) + if(target->IsAppBundleOnApple()) { value += itgen->GetInstallFilename(target, config); value += ".app/Contents/MacOS/"; @@ -395,13 +402,14 @@ cmExportInstallFileGenerator::HandleMissingTarget( std::string& link_libs, std::vector<std::string>& missingTargets, cmMakefile* mf, cmTarget* depender, cmTarget* dependee) { - std::string name = dependee->GetName(); + const std::string name = dependee->GetName(); std::vector<std::string> namespaces = this->FindNamespaces(mf, name); int targetOccurrences = (int)namespaces.size(); if (targetOccurrences == 1) { std::string missingTarget = namespaces[0]; - missingTarget += name; + + missingTarget += dependee->GetExportName(); link_libs += missingTarget; missingTargets.push_back(missingTarget); } @@ -496,3 +504,19 @@ cmExportInstallFileGenerator } cmSystemTools::Error(e.str().c_str()); } + +std::string +cmExportInstallFileGenerator::InstallNameDir(cmTarget* target, + const std::string&) +{ + std::string install_name_dir; + + cmMakefile* mf = target->GetMakefile(); + if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + install_name_dir = + target->GetInstallNameDirForInstallTree(); + } + + return install_name_dir; +} diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 20dd57ad1..7c634a4d8 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -85,6 +85,8 @@ protected: void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen); + std::string InstallNameDir(cmTarget* target, const std::string& config); + cmInstallExportGenerator* IEGen; std::string ImportPrefix; diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 75f2651ba..819ac371e 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -31,8 +31,10 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os) ImportPropertyMap properties; - this->FindTargets("INTERFACE_INCLUDE_DIRECTORIES", te, emittedDeps); - this->FindTargets("INTERFACE_COMPILE_DEFINITIONS", te, emittedDeps); +#define FIND_TARGETS(PROPERTY) \ + this->FindTargets(#PROPERTY, te, emittedDeps); + + CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(FIND_TARGETS) this->PopulateProperties(te, properties, emittedDeps); @@ -91,7 +93,9 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget* target, { properties[i->first] = i->second.GetValue(); - if(i->first.find("IMPORTED_LINK_INTERFACE_LIBRARIES") == 0) + if(i->first.find("IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 + || i->first.find("IMPORTED_LINK_DEPENDENT_LIBRARIES") == 0 + || i->first.find("INTERFACE_LINK_LIBRARIES") == 0) { const std::string libs = i->second.GetValue(); @@ -112,3 +116,18 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget* target, } } } +std::string +cmExportTryCompileFileGenerator::InstallNameDir(cmTarget* target, + const std::string& config) +{ + std::string install_name_dir; + + cmMakefile* mf = target->GetMakefile(); + if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + install_name_dir = + target->GetInstallNameDirForBuildTree(config.c_str()); + } + + return install_name_dir; +} diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index ed393abf4..91b4a6153 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -43,6 +43,8 @@ protected: ImportPropertyMap& properties, std::set<cmTarget*> &emitted); + std::string InstallNameDir(cmTarget* target, + const std::string& config); private: std::string FindTargets(const char *prop, cmTarget *tgt, std::set<cmTarget*> &emitted); diff --git a/Source/cmExprLexer.cxx b/Source/cmExprLexer.cxx index 53dfca7c0..9947c77f1 100644 --- a/Source/cmExprLexer.cxx +++ b/Source/cmExprLexer.cxx @@ -693,9 +693,9 @@ extern int cmExpr_yylex (yyscan_t yyscanner); */ YY_DECL { - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; #line 86 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l" @@ -745,7 +745,7 @@ YY_DECL yy_match: do { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -989,9 +989,9 @@ return 0; /* this should not happen but it silences a warning*/ static int yy_get_next_buffer (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = yyg->yytext_ptr; - register int number_to_move, i; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = yyg->yytext_ptr; + int number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) @@ -1116,15 +1116,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner) static yy_state_type yy_get_previous_state (yyscan_t yyscanner) { - register yy_state_type yy_current_state; - register char *yy_cp; + yy_state_type yy_current_state; + char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_current_state = yyg->yy_start; for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1149,11 +1149,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) { - register int yy_is_jam; + int yy_is_jam; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - register char *yy_cp = yyg->yy_c_buf_p; + char *yy_cp = yyg->yy_c_buf_p; - register YY_CHAR yy_c = 1; + YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1867,7 +1867,7 @@ int cmExpr_yylex_destroy (yyscan_t yyscanner) #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) { - register int i; + int i; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; @@ -1877,7 +1877,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) { - register int n; + int n; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; for ( n = 0; s[n]; ++n ) ; diff --git a/Source/cmExprLexer.in.l b/Source/cmExprLexer.in.l index f344b40ff..febd244fe 100644 --- a/Source/cmExprLexer.in.l +++ b/Source/cmExprLexer.in.l @@ -20,6 +20,7 @@ Run flex like this: Modify cmExprLexer.cxx: - remove TABs + - remove use of the 'register' storage class specifier - remove "yyscanner" argument from these methods: yy_fatal_error, cmExpr_yyalloc, cmExpr_yyrealloc, cmExpr_yyfree - remove all YY_BREAK lines occurring right after return statements diff --git a/Source/cmExprParser.cxx b/Source/cmExprParser.cxx index 5c164a081..77880c0a3 100644 --- a/Source/cmExprParser.cxx +++ b/Source/cmExprParser.cxx @@ -267,7 +267,7 @@ union yyalloc # define YYCOPY(To, From, Count) \ do \ { \ - register YYSIZE_T yyi; \ + YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ @@ -696,7 +696,7 @@ yystrlen (yystr) const char *yystr; # endif { - register const char *yys = yystr; + const char *yys = yystr; while (*yys++ != '\0') continue; @@ -721,8 +721,8 @@ yystpcpy (yydest, yysrc) const char *yysrc; # endif { - register char *yyd = yydest; - register const char *yys = yysrc; + char *yyd = yydest; + const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; @@ -852,8 +852,8 @@ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; - register int yystate; - register int yyn; + int yystate; + int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; @@ -871,12 +871,12 @@ int yynerrs; /* The state stack. */ short int yyssa[YYINITDEPTH]; short int *yyss = yyssa; - register short int *yyssp; + short int *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; - register YYSTYPE *yyvsp; + YYSTYPE *yyvsp; diff --git a/Source/cmExprParser.y b/Source/cmExprParser.y index 317b0ba98..12c2e4806 100644 --- a/Source/cmExprParser.y +++ b/Source/cmExprParser.y @@ -20,6 +20,7 @@ Run bison like this: Modify cmExprParser.cxx: - remove TABs + - remove use of the 'register' storage class specifier - add __HP_aCC to the #if test for yyerrorlab warning suppression */ diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx index 9c1795ec2..cc35f84cd 100644 --- a/Source/cmExprParserHelper.cxx +++ b/Source/cmExprParserHelper.cxx @@ -12,10 +12,10 @@ #include "cmExprParserHelper.h" #include "cmSystemTools.h" -#include "cmExprLexer.h" - #include "cmMakefile.h" +#include "cmExprLexer.h" + int cmExpr_yyparse( yyscan_t yyscanner ); // cmExprParserHelper::cmExprParserHelper() diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index f6f4ceff3..dfbb1c0ad 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -621,19 +621,15 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout, ->GetGeneratorTarget(target); // the compilerdefines for this target - std::string cdefs = target->GetCompileDefinitions(buildType); + std::vector<std::string> cdefs; + target->GetCompileDefinitions(cdefs, buildType); - if(!cdefs.empty()) + // Expand the list. + for(std::vector<std::string>::const_iterator di = cdefs.begin(); + di != cdefs.end(); ++di) { - // Expand the list. - std::vector<std::string> defs; - cmSystemTools::ExpandListArgument(cdefs.c_str(), defs); - for(std::vector<std::string>::const_iterator di = defs.begin(); - di != defs.end(); ++di) - { - cmXMLSafe safedef(di->c_str()); - fout <<" <Add option=\"-D" << safedef.str() << "\" />\n"; - } + cmXMLSafe safedef(di->c_str()); + fout <<" <Add option=\"-D" << safedef.str() << "\" />\n"; } // the include directories for this target diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 97ab0863c..d80e775bf 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -39,6 +39,7 @@ cmExtraEclipseCDT4Generator this->SupportsVirtualFolders = true; this->GenerateLinkedResources = true; + this->SupportsGmakeErrorParser = true; } //---------------------------------------------------------------------------- @@ -50,7 +51,7 @@ void cmExtraEclipseCDT4Generator entry.Full = "Project files for Eclipse will be created in the top directory. " "In out of source builds, a linked resource to the top level source " - "directory will be created." + "directory will be created. " "Additionally a hierarchy of makefiles is generated into the " "build tree. The appropriate make program can build the project through " "the default make target. A \"make install\" target is also provided."; @@ -77,6 +78,10 @@ void cmExtraEclipseCDT4Generator::Generate() { this->SupportsVirtualFolders = false; } + if (version < 3007) // 3.7 is Indigo + { + this->SupportsGmakeErrorParser = false; + } } } @@ -403,8 +408,17 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() { fout << "org.eclipse.cdt.core.ICCErrorParser;"; } + + if (this->SupportsGmakeErrorParser) + { + fout << "org.eclipse.cdt.core.GmakeErrorParser;"; + } + else + { + fout << "org.eclipse.cdt.core.MakeErrorParser;"; + } + fout << - "org.eclipse.cdt.core.MakeErrorParser;" "org.eclipse.cdt.core.GCCErrorParser;" "org.eclipse.cdt.core.GASErrorParser;" "org.eclipse.cdt.core.GLDErrorParser;" @@ -540,12 +554,15 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets( fileIt != sFiles.end(); ++fileIt) { - std::string linkName4 = linkName3; - linkName4 += "/"; - linkName4 += - cmSystemTools::GetFilenameName((*fileIt)->GetFullPath()); - this->AppendLinkedResource(fout, linkName4, - (*fileIt)->GetFullPath(), LinkToFile); + std::string fullPath = (*fileIt)->GetFullPath(); + if (!cmSystemTools::FileIsDirectory(fullPath.c_str())) + { + std::string linkName4 = linkName3; + linkName4 += "/"; + linkName4 += cmSystemTools::GetFilenameName(fullPath); + this->AppendLinkedResource(fout, linkName4, + fullPath, LinkToFile); + } } } } diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h index 31ad68da9..b31cce74c 100644 --- a/Source/cmExtraEclipseCDT4Generator.h +++ b/Source/cmExtraEclipseCDT4Generator.h @@ -111,6 +111,7 @@ private: bool GenerateSourceProject; bool GenerateLinkedResources; bool SupportsVirtualFolders; + bool SupportsGmakeErrorParser; }; diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index e4802d59e..523fca9aa 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -421,7 +421,7 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source, std::vector<std::string> includes; lg->GetIncludeDirectories(includes, gtgt, language, config); std::string includeFlags = - lg->GetIncludeFlags(includes, language, true); // full include paths + lg->GetIncludeFlags(includes, gtgt, language, true); // full include paths lg->AppendFlags(flags, includeFlags.c_str()); } @@ -429,35 +429,10 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source, lg->AppendFlags(flags, makefile->GetDefineFlags()); // Add target-specific flags. - if(target->GetProperty("COMPILE_FLAGS")) - { - std::string langIncludeExpr = "CMAKE_"; - langIncludeExpr += language; - langIncludeExpr += "_FLAG_REGEX"; - const char* regex = makefile->GetDefinition(langIncludeExpr.c_str()); - if(regex) - { - cmsys::RegularExpression r(regex); - std::vector<std::string> args; - cmSystemTools:: - ParseWindowsCommandLine(target->GetProperty("COMPILE_FLAGS"), args); - for(std::vector<std::string>::iterator i = args.begin(); - i != args.end(); ++i) - { - if(r.find(i->c_str())) - { - lg->AppendFlags(flags, i->c_str()); - } - } - } - else - { - lg->AppendFlags(flags, target->GetProperty("COMPILE_FLAGS")); - } - } + lg->AddCompileOptions(flags, target, config, language); // Add source file specific flags. - lg->AppendFlags(flags, target->GetProperty("COMPILE_FLAGS")); + lg->AppendFlags(flags, source->GetProperty("COMPILE_FLAGS")); // TODO: Handle Apple frameworks. @@ -488,7 +463,7 @@ ComputeDefines(cmSourceFile *source, cmLocalGenerator* lg, cmTarget *target, } // Add preprocessor definitions for this target and configuration. - lg->AppendDefines(defines, target->GetCompileDefinitions(config)); + lg->AddCompileDefinitions(defines, target, config); lg->AppendDefines(defines, source->GetProperty("COMPILE_DEFINITIONS")); { std::string defPropName = "COMPILE_DEFINITIONS_"; diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 018ce7ecd..4446f7216 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -167,6 +167,10 @@ bool cmFileCommand { return this->HandleTimestampCommand(args); } + else if ( subCommand == "GENERATE" ) + { + return this->HandleGenerateCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -1970,7 +1974,7 @@ bool cmFileInstaller else { cmOStringStream e; - e << "Option TYPE given uknown value \"" << stype << "\"."; + e << "Option TYPE given unknown value \"" << stype << "\"."; this->FileCommand->SetError(e.str().c_str()); return false; } @@ -1985,7 +1989,7 @@ bool cmFileInstaller::HandleInstallDestination() // allow for / to be a valid destination if ( destination.size() < 2 && destination != "/" ) { - this->FileCommand->SetError("called with inapropriate arguments. " + this->FileCommand->SetError("called with inappropriate arguments. " "No DESTINATION provided or ."); return false; } @@ -2485,7 +2489,7 @@ namespace { cmWriteToFileCallback(void *ptr, size_t size, size_t nmemb, void *data) { - register int realsize = (int)(size * nmemb); + int realsize = (int)(size * nmemb); std::ofstream* fout = static_cast<std::ofstream*>(data); const char* chPtr = static_cast<char*>(ptr); fout->write(chPtr, realsize); @@ -2497,7 +2501,7 @@ namespace { cmWriteToMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) { - register int realsize = (int)(size * nmemb); + int realsize = (int)(size * nmemb); cmFileCommandVectorOfChar *vec = static_cast<cmFileCommandVectorOfChar*>(data); const char* chPtr = static_cast<char*>(ptr); @@ -3250,6 +3254,80 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) } //---------------------------------------------------------------------------- +void cmFileCommand::AddEvaluationFile(const std::string &inputName, + const std::string &outputExpr, + const std::string &condition, + bool inputIsContent + ) +{ + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + + cmGeneratorExpression outputGe(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputCge + = outputGe.Parse(outputExpr); + + cmGeneratorExpression conditionGe(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> conditionCge + = conditionGe.Parse(condition); + + this->Makefile->GetLocalGenerator() + ->GetGlobalGenerator()->AddEvaluationFile(inputName, + outputCge, + this->Makefile, + conditionCge, + inputIsContent); +} + +//---------------------------------------------------------------------------- +bool cmFileCommand::HandleGenerateCommand( + std::vector<std::string> const& args) +{ + if (args.size() < 5) + { + this->SetError("Incorrect arguments to GENERATE subcommand."); + return false; + } + if (args[1] != "OUTPUT") + { + this->SetError("Incorrect arguments to GENERATE subcommand."); + return false; + } + std::string condition; + if (args.size() > 5) + { + if (args[5] != "CONDITION") + { + this->SetError("Incorrect arguments to GENERATE subcommand."); + return false; + } + if (args.size() != 7) + { + this->SetError("Incorrect arguments to GENERATE subcommand."); + return false; + } + condition = args[6]; + if (condition.empty()) + { + this->SetError("CONDITION of sub-command GENERATE must not be empty if " + "specified."); + return false; + } + } + std::string output = args[2]; + const bool inputIsContent = args[3] != "INPUT"; + if (inputIsContent && args[3] != "CONTENT") + { + this->SetError("Incorrect arguments to GENERATE subcommand."); + return false; + } + std::string input = args[4]; + + this->AddEvaluationFile(input, output, condition, inputIsContent); + return true; +} + +//---------------------------------------------------------------------------- bool cmFileCommand::HandleTimestampCommand( std::vector<std::string> const& args) { diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 5973fa732..aa755d1f5 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -88,6 +88,9 @@ public: " file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n" " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n" " file(TIMESTAMP filename variable [<format string>] [UTC])\n" + " file(GENERATE OUTPUT output_file\n" + " <INPUT input_file|CONTENT input_content>\n" + " [CONDITION expression])\n" "WRITE will write a message into a file called 'filename'. It " "overwrites the file if it already exists, and creates the file " "if it does not exist. (If the file is a build input, use " @@ -231,6 +234,15 @@ public: "it prints status messages, and NO_SOURCE_PERMISSIONS is default. " "Installation scripts generated by the install() command use this " "signature (with some undocumented options for internal use)." + "\n" + "GENERATE will write an <output_file> with content from an " + "<input_file>, or from <input_content>. The output is generated " + "conditionally based on the content of the <condition>. The file is " + "written at CMake generate-time and the input may contain generator " + "expressions. The <condition>, <output_file> and <input_file> may " + "also contain generator expressions. The <condition> must evaluate to " + "either '0' or '1'. The <output_file> must evaluate to a unique name " + "among all configurations and among all invocations of file(GENERATE)." // Undocumented INSTALL options: // - RENAME <name> // - OPTIONAL @@ -269,6 +281,13 @@ protected: bool HandleUploadCommand(std::vector<std::string> const& args); bool HandleTimestampCommand(std::vector<std::string> const& args); + bool HandleGenerateCommand(std::vector<std::string> const& args); + +private: + void AddEvaluationFile(const std::string &inputName, + const std::string &outputExpr, + const std::string &condition, + bool inputIsContent); }; diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index 10b47b9e0..a126cd110 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -267,7 +267,7 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf) std::vector<std::string> expandedArguments; mf.ExpandArguments(lff.Arguments, expandedArguments); // if the endfunction has arguments then make sure - // they match the ones in the openeing function command + // they match the ones in the opening function command if ((expandedArguments.empty() || (expandedArguments[0] == this->Args[0]))) { diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index ab8bd137e..d73c72c10 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -192,11 +192,12 @@ static std::string stripAllGeneratorExpressions(const std::string &input) std::string result; std::string::size_type pos = 0; std::string::size_type lastPos = pos; + int nestingLevel = 0; while((pos = input.find("$<", lastPos)) != input.npos) { result += input.substr(lastPos, pos - lastPos); pos += 2; - int nestingLevel = 1; + nestingLevel = 1; const char *c = input.c_str() + pos; const char * const cStart = c; for ( ; *c; ++c) @@ -224,16 +225,42 @@ static std::string stripAllGeneratorExpressions(const std::string &input) pos += traversed; lastPos = pos; } - result += input.substr(lastPos); + if (nestingLevel == 0) + { + result += input.substr(lastPos); + } return cmGeneratorExpression::StripEmptyListElements(result); } //---------------------------------------------------------------------------- +static void prefixItems(const std::string &content, std::string &result, + const std::string &prefix) +{ + std::vector<std::string> entries; + cmGeneratorExpression::Split(content, entries); + const char *sep = ""; + for(std::vector<std::string>::const_iterator ei = entries.begin(); + ei != entries.end(); ++ei) + { + result += sep; + sep = ";"; + if (!cmSystemTools::FileIsFullPath(ei->c_str()) + && cmGeneratorExpression::Find(*ei) == std::string::npos) + { + result += prefix; + } + result += *ei; + } +} + +//---------------------------------------------------------------------------- static std::string stripExportInterface(const std::string &input, - cmGeneratorExpression::PreprocessContext context) + cmGeneratorExpression::PreprocessContext context, + bool resolveRelative) { std::string result; + int nestingLevel = 0; std::string::size_type pos = 0; std::string::size_type lastPos = pos; while (true) @@ -263,7 +290,7 @@ static std::string stripExportInterface(const std::string &input, const bool gotInstallInterface = input[pos + 2] == 'I'; pos += gotInstallInterface ? sizeof("$<INSTALL_INTERFACE:") - 1 : sizeof("$<BUILD_INTERFACE:") - 1; - int nestingLevel = 1; + nestingLevel = 1; const char *c = input.c_str() + pos; const char * const cStart = c; for ( ; *c; ++c) @@ -289,7 +316,15 @@ static std::string stripExportInterface(const std::string &input, else if(context == cmGeneratorExpression::InstallInterface && gotInstallInterface) { - result += input.substr(pos, c - cStart); + const std::string content = input.substr(pos, c - cStart); + if (resolveRelative) + { + prefixItems(content, result, "${_IMPORT_PREFIX}/"); + } + else + { + result += content; + } } break; } @@ -304,7 +339,10 @@ static std::string stripExportInterface(const std::string &input, pos += traversed; lastPos = pos; } - result += input.substr(lastPos); + if (nestingLevel == 0) + { + result += input.substr(lastPos); + } return cmGeneratorExpression::StripEmptyListElements(result); } @@ -380,7 +418,8 @@ void cmGeneratorExpression::Split(const std::string &input, //---------------------------------------------------------------------------- std::string cmGeneratorExpression::Preprocess(const std::string &input, - PreprocessContext context) + PreprocessContext context, + bool resolveRelative) { if (context == StripAllGeneratorExpressions) { @@ -388,7 +427,7 @@ std::string cmGeneratorExpression::Preprocess(const std::string &input, } else if (context == BuildInterface || context == InstallInterface) { - return stripExportInterface(input, context); + return stripExportInterface(input, context, resolveRelative); } assert(!"cmGeneratorExpression::Preprocess called with invalid args"); diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 86b6f25df..c20f130c9 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -57,7 +57,8 @@ public: }; static std::string Preprocess(const std::string &input, - PreprocessContext context); + PreprocessContext context, + bool resolveRelative = false); static void Split(const std::string &input, std::vector<std::string> &output); diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 5cb50b9b8..92dc054c9 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -22,7 +22,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( const GeneratorExpressionContent *content, cmGeneratorExpressionDAGChecker *parent) : Parent(parent), Target(target), Property(property), - Content(content), Backtrace(backtrace) + Content(content), Backtrace(backtrace), TransitivePropertiesOnly(false) { const cmGeneratorExpressionDAGChecker *top = this; const cmGeneratorExpressionDAGChecker *p = this->Parent; @@ -33,8 +33,13 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker( } this->CheckResult = this->checkGraph(); - if (CheckResult == DAG && (top->EvaluatingIncludeDirectories() - || top->EvaluatingCompileDefinitions())) +#define TEST_TRANSITIVE_PROPERTY_METHOD(METHOD) \ + top->METHOD () || + + if (CheckResult == DAG && ( + CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(TEST_TRANSITIVE_PROPERTY_METHOD) + false) + ) { std::map<cmStdString, std::set<cmStdString> >::const_iterator it = top->Seen.find(target); @@ -134,7 +139,21 @@ cmGeneratorExpressionDAGChecker::checkGraph() const } //---------------------------------------------------------------------------- -bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries() +bool cmGeneratorExpressionDAGChecker::GetTransitivePropertiesOnly() +{ + const cmGeneratorExpressionDAGChecker *top = this; + const cmGeneratorExpressionDAGChecker *parent = this->Parent; + while (parent) + { + top = parent; + parent = parent->Parent; + } + + return top->TransitivePropertiesOnly; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt) { const cmGeneratorExpressionDAGChecker *top = this; const cmGeneratorExpressionDAGChecker *parent = this->Parent; @@ -145,11 +164,18 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries() } const char *prop = top->Property.c_str(); + + if (tgt) + { + return top->Target == tgt && strcmp(prop, "LINK_LIBRARIES") == 0; + } + return (strcmp(prop, "LINK_LIBRARIES") == 0 || strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0 || strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 || strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 25) == 0 - || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0); + || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0) + || strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0; } //---------------------------------------------------------------------------- @@ -161,6 +187,14 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingIncludeDirectories() const } //---------------------------------------------------------------------------- +bool +cmGeneratorExpressionDAGChecker::EvaluatingSystemIncludeDirectories() const +{ + const char *prop = this->Property.c_str(); + return strcmp(prop, "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES") == 0; +} + +//---------------------------------------------------------------------------- bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const { const char *prop = this->Property.c_str(); @@ -168,3 +202,11 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const || strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0 || strncmp(prop, "COMPILE_DEFINITIONS_", 20) == 0); } + +//---------------------------------------------------------------------------- +bool cmGeneratorExpressionDAGChecker::EvaluatingCompileOptions() const +{ + const char *prop = this->Property.c_str(); + return (strcmp(prop, "COMPILE_OPTIONS") == 0 + || strcmp(prop, "INTERFACE_COMPILE_OPTIONS") == 0 ); +} diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index 62a5cdf38..0b7ef025c 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -16,6 +16,18 @@ #include "cmGeneratorExpressionEvaluator.h" +#define CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(F) \ + F(EvaluatingIncludeDirectories) \ + F(EvaluatingSystemIncludeDirectories) \ + F(EvaluatingCompileDefinitions) \ + F(EvaluatingCompileOptions) + +#define CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(F) \ + F(INTERFACE_INCLUDE_DIRECTORIES) \ + F(INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) \ + F(INTERFACE_COMPILE_DEFINITIONS) \ + F(INTERFACE_COMPILE_OPTIONS) + //---------------------------------------------------------------------------- struct cmGeneratorExpressionDAGChecker { @@ -37,9 +49,16 @@ struct cmGeneratorExpressionDAGChecker void reportError(cmGeneratorExpressionContext *context, const std::string &expr); - bool EvaluatingLinkLibraries(); - bool EvaluatingIncludeDirectories() const; - bool EvaluatingCompileDefinitions() const; + bool EvaluatingLinkLibraries(const char *tgt = 0); + +#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) \ + bool METHOD () const; + +CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(DECLARE_TRANSITIVE_PROPERTY_METHOD) + + bool GetTransitivePropertiesOnly(); + void SetTransitivePropertiesOnly() + { this->TransitivePropertiesOnly = true; } private: Result checkGraph() const; @@ -52,6 +71,7 @@ private: const GeneratorExpressionContent * const Content; const cmListFileBacktrace Backtrace; Result CheckResult; + bool TransitivePropertiesOnly; }; #endif diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx new file mode 100644 index 000000000..cab99ed04 --- /dev/null +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -0,0 +1,151 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmGeneratorExpressionEvaluationFile.h" + +#include "cmMakefile.h" + +#include <assert.h> + +//---------------------------------------------------------------------------- +cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile( + const std::string &input, + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr, + cmMakefile *makefile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, + bool inputIsContent) + : Input(input), + OutputFileExpr(outputFileExpr), + Makefile(makefile), + Condition(condition), + InputIsContent(inputIsContent) +{ +} + +//---------------------------------------------------------------------------- +void cmGeneratorExpressionEvaluationFile::Generate(const char *config, + cmCompiledGeneratorExpression* inputExpression, + std::map<std::string, std::string> &outputFiles) +{ + std::string rawCondition = this->Condition->GetInput(); + if (!rawCondition.empty()) + { + std::string condResult = this->Condition->Evaluate(this->Makefile, config); + if (condResult == "0") + { + return; + } + if (condResult != "1") + { + cmOStringStream e; + e << "Evaluation file condition \"" << rawCondition << "\" did " + "not evaluate to valid content. Got \"" << condResult << "\"."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } + } + + const std::string outputFileName + = this->OutputFileExpr->Evaluate(this->Makefile, config); + const std::string outputContent + = inputExpression->Evaluate(this->Makefile, config); + + std::map<std::string, std::string>::iterator it + = outputFiles.find(outputFileName); + + if(it != outputFiles.end()) + { + if (it->second == outputContent) + { + return; + } + cmOStringStream e; + e << "Evaluation file to be written multiple times for different " + "configurations with different content:\n " << outputFileName; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } + + this->Files.push_back(outputFileName); + outputFiles[outputFileName] = outputContent; + + std::ofstream fout(outputFileName.c_str()); + + if(!fout) + { + cmOStringStream e; + e << "Evaluation file \"" << outputFileName << "\" cannot be written."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } + + fout << outputContent; + + fout.close(); +} + +//---------------------------------------------------------------------------- +void cmGeneratorExpressionEvaluationFile::Generate() +{ + std::string inputContent; + if (this->InputIsContent) + { + inputContent = this->Input; + } + else + { + std::ifstream fin(this->Input.c_str()); + if(!fin) + { + cmOStringStream e; + e << "Evaluation file \"" << this->Input << "\" cannot be read."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } + + std::string line; + std::string sep; + while(cmSystemTools::GetLineFromStream(fin, line)) + { + inputContent += sep + line; + sep = "\n"; + } + inputContent += sep; + } + + cmListFileBacktrace lfbt = this->OutputFileExpr->GetBacktrace(); + cmGeneratorExpression contentGE(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> inputExpression + = contentGE.Parse(inputContent); + + std::map<std::string, std::string> outputFiles; + + std::vector<std::string> allConfigs; + this->Makefile->GetConfigurations(allConfigs); + + if (allConfigs.empty()) + { + this->Generate(0, inputExpression.get(), outputFiles); + } + else + { + for(std::vector<std::string>::const_iterator li = allConfigs.begin(); + li != allConfigs.end(); ++li) + { + this->Generate(li->c_str(), inputExpression.get(), outputFiles); + if(cmSystemTools::GetFatalErrorOccured()) + { + return; + } + } + } +} diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h new file mode 100644 index 000000000..20ee5cb2d --- /dev/null +++ b/Source/cmGeneratorExpressionEvaluationFile.h @@ -0,0 +1,48 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmGeneratorExpressionEvaluationFile_h +#define cmGeneratorExpressionEvaluationFile_h + +#include "cmStandardIncludes.h" +#include <cmsys/auto_ptr.hxx> + +#include "cmGeneratorExpression.h" + +//---------------------------------------------------------------------------- +class cmGeneratorExpressionEvaluationFile +{ +public: + cmGeneratorExpressionEvaluationFile(const std::string &input, + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr, + cmMakefile *makefile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, + bool inputIsContent); + + void Generate(); + + std::vector<std::string> GetFiles() const { return this->Files; } + +private: + void Generate(const char *config, + cmCompiledGeneratorExpression* inputExpression, + std::map<std::string, std::string> &outputFiles); + +private: + const std::string Input; + const cmsys::auto_ptr<cmCompiledGeneratorExpression> OutputFileExpr; + cmMakefile *Makefile; + const cmsys::auto_ptr<cmCompiledGeneratorExpression> Condition; + std::vector<std::string> Files; + const bool InputIsContent; +}; + +#endif diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index a01a0f890..8b3135412 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -45,13 +45,18 @@ void reportError(cmGeneratorExpressionContext *context, //---------------------------------------------------------------------------- struct cmGeneratorExpressionNode { + enum { + DynamicParameters = 0, + OneOrMoreParameters = -1, + ZeroOrMoreParameters = -2 + }; virtual ~cmGeneratorExpressionNode() {} virtual bool GeneratesContent() const { return true; } virtual bool RequiresLiteralInput() const { return false; } - virtual bool AcceptsSingleArbitraryContentParameter() const + virtual bool AcceptsArbitraryContentParameter() const { return false; } virtual int NumExpectedParameters() const { return 1; } @@ -70,7 +75,7 @@ static const struct ZeroNode : public cmGeneratorExpressionNode virtual bool GeneratesContent() const { return false; } - virtual bool AcceptsSingleArbitraryContentParameter() const { return true; } + virtual bool AcceptsArbitraryContentParameter() const { return true; } std::string Evaluate(const std::vector<std::string> &, cmGeneratorExpressionContext *, @@ -87,7 +92,7 @@ static const struct OneNode : public cmGeneratorExpressionNode { OneNode() {} - virtual bool AcceptsSingleArbitraryContentParameter() const { return true; } + virtual bool AcceptsArbitraryContentParameter() const { return true; } std::string Evaluate(const std::vector<std::string> &, cmGeneratorExpressionContext *, @@ -110,8 +115,7 @@ static const struct ZeroNode installInterfaceNode; static const struct OP ## Node : public cmGeneratorExpressionNode \ { \ OP ## Node () {} \ -/* We let -1 carry the meaning 'at least one' */ \ - virtual int NumExpectedParameters() const { return -1; } \ + virtual int NumExpectedParameters() const { return OneOrMoreParameters; } \ \ std::string Evaluate(const std::vector<std::string> ¶meters, \ cmGeneratorExpressionContext *context, \ @@ -243,6 +247,269 @@ static const struct SemicolonNode : public cmGeneratorExpressionNode } semicolonNode; //---------------------------------------------------------------------------- +struct CompilerIdNode : public cmGeneratorExpressionNode +{ + CompilerIdNode() {} + + virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; } + + std::string EvaluateWithLanguage(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *, + const std::string &lang) const + { + const char *compilerId = context->Makefile ? + context->Makefile->GetSafeDefinition(( + "CMAKE_" + lang + "_COMPILER_ID").c_str()) : ""; + if (parameters.size() == 0) + { + return compilerId ? compilerId : ""; + } + cmsys::RegularExpression compilerIdValidator; + compilerIdValidator.compile("^[A-Za-z0-9_]*$"); + if (!compilerIdValidator.find(parameters.begin()->c_str())) + { + reportError(context, content->GetOriginalExpression(), + "Expression syntax not recognized."); + return std::string(); + } + if (!compilerId) + { + return parameters.front().empty() ? "1" : "0"; + } + + if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0) + { + return "1"; + } + return "0"; + } +}; + +//---------------------------------------------------------------------------- +static const struct CCompilerIdNode : public CompilerIdNode +{ + CCompilerIdNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagChecker) const + { + if (parameters.size() != 0 && parameters.size() != 1) + { + reportError(context, content->GetOriginalExpression(), + "$<C_COMPILER_ID> expression requires one or two parameters"); + return std::string(); + } + if (!context->HeadTarget) + { + reportError(context, content->GetOriginalExpression(), + "$<C_COMPILER_ID> may only be used with targets. It may not " + "be used with add_custom_command."); + } + return this->EvaluateWithLanguage(parameters, context, content, + dagChecker, "C"); + } +} cCompilerIdNode; + +//---------------------------------------------------------------------------- +static const struct CXXCompilerIdNode : public CompilerIdNode +{ + CXXCompilerIdNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagChecker) const + { + if (parameters.size() != 0 && parameters.size() != 1) + { + reportError(context, content->GetOriginalExpression(), + "$<CXX_COMPILER_ID> expression requires one or two parameters"); + return std::string(); + } + if (!context->HeadTarget) + { + reportError(context, content->GetOriginalExpression(), + "$<CXX_COMPILER_ID> may only be used with targets. It may not " + "be used with add_custom_command."); + } + return this->EvaluateWithLanguage(parameters, context, content, + dagChecker, "CXX"); + } +} cxxCompilerIdNode; + +//---------------------------------------------------------------------------- +struct CompilerVersionNode : public cmGeneratorExpressionNode +{ + CompilerVersionNode() {} + + virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; } + + std::string EvaluateWithLanguage(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *, + const std::string &lang) const + { + const char *compilerVersion = context->Makefile ? + context->Makefile->GetSafeDefinition(( + "CMAKE_" + lang + "_COMPILER_VERSION").c_str()) : ""; + if (parameters.size() == 0) + { + return compilerVersion ? compilerVersion : ""; + } + + cmsys::RegularExpression compilerIdValidator; + compilerIdValidator.compile("^[0-9\\.]*$"); + if (!compilerIdValidator.find(parameters.begin()->c_str())) + { + reportError(context, content->GetOriginalExpression(), + "Expression syntax not recognized."); + return std::string(); + } + if (!compilerVersion) + { + return parameters.front().empty() ? "1" : "0"; + } + + return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, + parameters.begin()->c_str(), + compilerVersion) ? "1" : "0"; + } +}; + +//---------------------------------------------------------------------------- +static const struct CCompilerVersionNode : public CompilerVersionNode +{ + CCompilerVersionNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagChecker) const + { + if (parameters.size() != 0 && parameters.size() != 1) + { + reportError(context, content->GetOriginalExpression(), + "$<C_COMPILER_VERSION> expression requires one or two parameters"); + return std::string(); + } + if (!context->HeadTarget) + { + reportError(context, content->GetOriginalExpression(), + "$<C_COMPILER_VERSION> may only be used with targets. It may not " + "be used with add_custom_command."); + } + return this->EvaluateWithLanguage(parameters, context, content, + dagChecker, "C"); + } +} cCompilerVersionNode; + +//---------------------------------------------------------------------------- +static const struct CxxCompilerVersionNode : public CompilerVersionNode +{ + CxxCompilerVersionNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagChecker) const + { + if (parameters.size() != 0 && parameters.size() != 1) + { + reportError(context, content->GetOriginalExpression(), + "$<CXX_COMPILER_VERSION> expression requires one or two " + "parameters"); + return std::string(); + } + if (!context->HeadTarget) + { + reportError(context, content->GetOriginalExpression(), + "$<CXX_COMPILER_VERSION> may only be used with targets. It may " + "not be used with add_custom_command."); + } + return this->EvaluateWithLanguage(parameters, context, content, + dagChecker, "CXX"); + } +} cxxCompilerVersionNode; + + +//---------------------------------------------------------------------------- +static const struct VersionGreaterNode : public cmGeneratorExpressionNode +{ + VersionGreaterNode() {} + + virtual int NumExpectedParameters() const { return 2; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER, + parameters.front().c_str(), + parameters[1].c_str()) ? "1" : "0"; + } +} versionGreaterNode; + +//---------------------------------------------------------------------------- +static const struct VersionLessNode : public cmGeneratorExpressionNode +{ + VersionLessNode() {} + + virtual int NumExpectedParameters() const { return 2; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, + parameters.front().c_str(), + parameters[1].c_str()) ? "1" : "0"; + } +} versionLessNode; + +//---------------------------------------------------------------------------- +static const struct VersionEqualNode : public cmGeneratorExpressionNode +{ + VersionEqualNode() {} + + virtual int NumExpectedParameters() const { return 2; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, + parameters.front().c_str(), + parameters[1].c_str()) ? "1" : "0"; + } +} versionEqualNode; + +//---------------------------------------------------------------------------- +static const struct LinkOnlyNode : public cmGeneratorExpressionNode +{ + LinkOnlyNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *dagChecker) const + { + if(!dagChecker->GetTransitivePropertiesOnly()) + { + return parameters.front(); + } + return ""; + } +} linkOnlyNode; + +//---------------------------------------------------------------------------- static const struct ConfigurationNode : public cmGeneratorExpressionNode { ConfigurationNode() {} @@ -297,20 +564,67 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode const char* loc = 0; const char* imp = 0; std::string suffix; - return context->CurrentTarget->GetMappedConfig(context->Config, + if (context->CurrentTarget->GetMappedConfig(context->Config, &loc, &imp, - suffix) ? "1" : "0"; + suffix)) + { + // This imported target has an appropriate location + // for this (possibly mapped) config. + // Check if there is a proper config mapping for the tested config. + std::vector<std::string> mappedConfigs; + std::string mapProp = "MAP_IMPORTED_CONFIG_"; + mapProp += cmSystemTools::UpperCase(context->Config); + if(const char* mapValue = + context->CurrentTarget->GetProperty(mapProp.c_str())) + { + cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue), + mappedConfigs); + return std::find(mappedConfigs.begin(), mappedConfigs.end(), + cmSystemTools::UpperCase(parameters.front())) + != mappedConfigs.end() ? "1" : "0"; + } + } } return "0"; } } configurationTestNode; +static const struct JoinNode : public cmGeneratorExpressionNode +{ + JoinNode() {} + + virtual int NumExpectedParameters() const { return 2; } + + virtual bool AcceptsArbitraryContentParameter() const { return true; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *, + const GeneratorExpressionContent *, + cmGeneratorExpressionDAGChecker *) const + { + std::string result; + + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(parameters.front(), list); + std::string sep; + for(std::vector<std::string>::const_iterator li = list.begin(); + li != list.end(); ++li) + { + result += sep + *li; + sep = parameters[1]; + } + return result; + } +} joinNode; + +#define TRANSITIVE_PROPERTY_NAME(PROPERTY) \ + , #PROPERTY //---------------------------------------------------------------------------- static const char* targetPropertyTransitiveWhitelist[] = { - "INTERFACE_INCLUDE_DIRECTORIES" - , "INTERFACE_COMPILE_DEFINITIONS" + 0 + CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME) }; std::string getLinkedTargetsContent(const std::vector<std::string> &libraries, @@ -373,7 +687,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode TargetPropertyNode() {} // This node handles errors on parameter count itself. - virtual int NumExpectedParameters() const { return -1; } + virtual int NumExpectedParameters() const { return OneOrMoreParameters; } std::string Evaluate(const std::vector<std::string> ¶meters, cmGeneratorExpressionContext *context, @@ -434,6 +748,18 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode "Target name not supported."); return std::string(); } + if(propertyName == "ALIASED_TARGET") + { + if(context->Makefile->IsAlias(targetName.c_str())) + { + if(cmTarget* tgt = + context->Makefile->FindTargetToUse(targetName.c_str())) + { + return tgt->GetName(); + } + } + return ""; + } target = context->Makefile->FindTargetToUse( targetName.c_str()); @@ -475,6 +801,20 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode assert(target); + if (propertyName == "LINKER_LANGUAGE") + { + if (target->LinkLanguagePropagatesToDependents() && + dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries()) + { + reportError(context, content->GetOriginalExpression(), + "LINKER_LANGUAGE target property can not be used while evaluating " + "link libraries for a static library"); + return std::string(); + } + const char *lang = target->GetLinkerLanguage(context->Config); + return lang ? lang : ""; + } + cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, target->GetName(), propertyName, @@ -490,7 +830,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode // No error. We just skip cyclic references. return std::string(); case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: - for (size_t i = 0; + for (size_t i = 1; i < (sizeof(targetPropertyTransitiveWhitelist) / sizeof(*targetPropertyTransitiveWhitelist)); ++i) @@ -518,8 +858,13 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode } else { - assert(dagCheckerParent->EvaluatingIncludeDirectories() - || dagCheckerParent->EvaluatingCompileDefinitions()); +#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) \ + dagCheckerParent->METHOD () || + + assert( + CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD( + ASSERT_TRANSITIVE_PROPERTY_METHOD) + false); } } @@ -532,29 +877,39 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { interfacePropertyName = "INTERFACE_INCLUDE_DIRECTORIES"; } + else if (propertyName == "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES") + { + interfacePropertyName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"; + } else if (propertyName == "INTERFACE_COMPILE_DEFINITIONS" || propertyName == "COMPILE_DEFINITIONS" || strncmp(propertyName.c_str(), "COMPILE_DEFINITIONS_", 20) == 0) { interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS"; } + else if (propertyName == "INTERFACE_COMPILE_OPTIONS" + || propertyName == "COMPILE_OPTIONS") + { + interfacePropertyName = "INTERFACE_COMPILE_OPTIONS"; + } cmTarget *headTarget = context->HeadTarget ? context->HeadTarget : target; - const char **transBegin = targetPropertyTransitiveWhitelist; + const char **transBegin = targetPropertyTransitiveWhitelist + 1; const char **transEnd = targetPropertyTransitiveWhitelist + (sizeof(targetPropertyTransitiveWhitelist) / sizeof(*targetPropertyTransitiveWhitelist)); if (std::find_if(transBegin, transEnd, TransitiveWhitelistCompare(propertyName)) != transEnd) { - const cmTarget::LinkInterface *iface = target->GetLinkInterface( - context->Config, - headTarget); - if(iface) + + std::vector<std::string> libs; + target->GetTransitivePropertyLinkLibraries(context->Config, + headTarget, libs); + if (!libs.empty()) { linkedTargetsContent = - getLinkedTargetsContent(iface->Libraries, target, + getLinkedTargetsContent(libs, target, headTarget, context, &dagChecker, interfacePropertyName); @@ -607,7 +962,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return linkedTargetsContent; } - for (size_t i = 0; + for (size_t i = 1; i < (sizeof(targetPropertyTransitiveWhitelist) / sizeof(*targetPropertyTransitiveWhitelist)); ++i) @@ -645,7 +1000,7 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode virtual bool GeneratesContent() const { return true; } - virtual bool AcceptsSingleArbitraryContentParameter() const { return true; } + virtual bool AcceptsArbitraryContentParameter() const { return true; } virtual bool RequiresLiteralInput() const { return true; } std::string Evaluate(const std::vector<std::string> ¶meters, @@ -662,10 +1017,13 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode //---------------------------------------------------------------------------- static const char* targetPolicyWhitelist[] = { - "CMP0003" - , "CMP0004" - , "CMP0008" - , "CMP0020" + 0 +#define TARGET_POLICY_STRING(POLICY) \ + , #POLICY + + CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING) + +#undef TARGET_POLICY_STRING }; cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy) @@ -676,10 +1034,7 @@ cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy) return tgt->GetPolicyStatus ## POLICY (); \ } \ - RETURN_POLICY(CMP0003) - RETURN_POLICY(CMP0004) - RETURN_POLICY(CMP0008) - RETURN_POLICY(CMP0020) + CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY) #undef RETURN_POLICY @@ -695,10 +1050,7 @@ cmPolicies::PolicyID policyForString(const char *policy_id) return cmPolicies:: POLICY_ID; \ } \ - RETURN_POLICY_ID(CMP0003) - RETURN_POLICY_ID(CMP0004) - RETURN_POLICY_ID(CMP0008) - RETURN_POLICY_ID(CMP0020) + CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID) #undef RETURN_POLICY_ID @@ -728,7 +1080,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode context->HadContextSensitiveCondition = true; - for (size_t i = 0; + for (size_t i = 1; i < (sizeof(targetPolicyWhitelist) / sizeof(*targetPolicyWhitelist)); ++i) @@ -754,8 +1106,17 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode } reportError(context, content->GetOriginalExpression(), "$<TARGET_POLICY:prop> may only be used with a limited number of " - "policies. Currently it may be used with policies CMP0003, CMP0004, " - "CMP0008 and CMP0020." + "policies. Currently it may be used with the following policies:\n" + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +#define TARGET_POLICY_LIST_ITEM(POLICY) \ + " * " STRINGIFY(POLICY) "\n" + + CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM) + +#undef TARGET_POLICY_LIST_ITEM ); return std::string(); } @@ -898,7 +1259,7 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode std::string Evaluate(const std::vector<std::string> ¶meters, cmGeneratorExpressionContext *context, const GeneratorExpressionContent *content, - cmGeneratorExpressionDAGChecker *) const + cmGeneratorExpressionDAGChecker *dagChecker) const { // Lookup the referenced target. std::string name = *parameters.begin(); @@ -916,13 +1277,20 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode "No target \"" + name + "\""); return std::string(); } - if(target->GetType() >= cmTarget::UTILITY && + if(target->GetType() >= cmTarget::OBJECT_LIBRARY && target->GetType() != cmTarget::UNKNOWN_LIBRARY) { ::reportError(context, content->GetOriginalExpression(), "Target \"" + name + "\" is not an executable or library."); return std::string(); } + if (dagChecker && dagChecker->EvaluatingLinkLibraries(name.c_str())) + { + ::reportError(context, content->GetOriginalExpression(), + "Expressions which require the linker language may not " + "be used while evaluating link libraries"); + return std::string(); + } context->DependTargets.insert(target); context->AllTargets.insert(target); @@ -974,6 +1342,20 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &orNode; else if (identifier == "NOT") return ¬Node; + else if (identifier == "C_COMPILER_ID") + return &cCompilerIdNode; + else if (identifier == "CXX_COMPILER_ID") + return &cxxCompilerIdNode; + else if (identifier == "VERSION_GREATER") + return &versionGreaterNode; + else if (identifier == "VERSION_LESS") + return &versionLessNode; + else if (identifier == "VERSION_EQUAL") + return &versionEqualNode; + else if (identifier == "C_COMPILER_VERSION") + return &cCompilerVersionNode; + else if (identifier == "CXX_COMPILER_VERSION") + return &cxxCompilerVersionNode; else if (identifier == "CONFIGURATION") return &configurationNode; else if (identifier == "CONFIG") @@ -1018,6 +1400,10 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &installInterfaceNode; else if (identifier == "INSTALL_PREFIX") return &installPrefixNode; + else if (identifier == "JOIN") + return &joinNode; + else if (identifier == "LINK_ONLY") + return &linkOnlyNode; return 0; } @@ -1038,6 +1424,57 @@ std::string GeneratorExpressionContent::GetOriginalExpression() const } //---------------------------------------------------------------------------- +std::string GeneratorExpressionContent::ProcessArbitraryContent( + const cmGeneratorExpressionNode *node, + const std::string &identifier, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator + pit) const +{ + std::string result; + + const + std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator + pend = this->ParamChildren.end(); + for ( ; pit != pend; ++pit) + { + std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it + = pit->begin(); + const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end + = pit->end(); + for ( ; it != end; ++it) + { + if (node->RequiresLiteralInput()) + { + if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) + { + reportError(context, this->GetOriginalExpression(), + "$<" + identifier + "> expression requires literal input."); + return std::string(); + } + } + result += (*it)->Evaluate(context, dagChecker); + if (context->HadError) + { + return std::string(); + } + } + if ((pit + 1) != pend) + { + result += ","; + } + } + if (node->RequiresLiteralInput()) + { + std::vector<std::string> parameters; + parameters.push_back(result); + return node->Evaluate(parameters, context, this, dagChecker); + } + return result; +} + +//---------------------------------------------------------------------------- std::string GeneratorExpressionContent::Evaluate( cmGeneratorExpressionContext *context, cmGeneratorExpressionDAGChecker *dagChecker) const @@ -1069,7 +1506,8 @@ std::string GeneratorExpressionContent::Evaluate( if (!node->GeneratesContent()) { - if (node->AcceptsSingleArbitraryContentParameter()) + if (node->NumExpectedParameters() == 1 + && node->AcceptsArbitraryContentParameter()) { if (this->ParamChildren.empty()) { @@ -1086,50 +1524,12 @@ std::string GeneratorExpressionContent::Evaluate( return std::string(); } - if (node->AcceptsSingleArbitraryContentParameter()) + if (node->NumExpectedParameters() == 1 + && node->AcceptsArbitraryContentParameter()) { - std::string result; - std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator - pit = this->ParamChildren.begin(); - const - std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator - pend = this->ParamChildren.end(); - for ( ; pit != pend; ++pit) - { - if (!result.empty()) - { - result += ","; - } - - std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it - = pit->begin(); - const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end - = pit->end(); - for ( ; it != end; ++it) - { - if (node->RequiresLiteralInput()) - { - if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) - { - reportError(context, this->GetOriginalExpression(), - "$<" + identifier + "> expression requires literal input."); - return std::string(); - } - } - result += (*it)->Evaluate(context, dagChecker); - if (context->HadError) - { - return std::string(); - } - } - } - if (node->RequiresLiteralInput()) - { - std::vector<std::string> parameters; - parameters.push_back(result); - return node->Evaluate(parameters, context, this, dagChecker); - } - return result; + return this->ProcessArbitraryContent(node, identifier, context, + dagChecker, + this->ParamChildren.begin()); } std::vector<std::string> parameters; @@ -1150,12 +1550,15 @@ std::string GeneratorExpressionContent::EvaluateParameters( cmGeneratorExpressionDAGChecker *dagChecker, std::vector<std::string> ¶meters) const { + const int numExpected = node->NumExpectedParameters(); { std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator pit = this->ParamChildren.begin(); const std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator pend = this->ParamChildren.end(); + const bool acceptsArbitraryContent + = node->AcceptsArbitraryContentParameter(); for ( ; pit != pend; ++pit) { std::string parameter; @@ -1172,11 +1575,22 @@ std::string GeneratorExpressionContent::EvaluateParameters( } } parameters.push_back(parameter); + if (acceptsArbitraryContent + && parameters.size() == (unsigned int)numExpected - 1) + { + assert(pit != pend); + std::string lastParam = this->ProcessArbitraryContent(node, identifier, + context, + dagChecker, + pit + 1); + parameters.push_back(lastParam); + return std::string(); + } } } - int numExpected = node->NumExpectedParameters(); - if ((numExpected != -1 && (unsigned int)numExpected != parameters.size())) + if ((numExpected > cmGeneratorExpressionNode::DynamicParameters + && (unsigned int)numExpected != parameters.size())) { if (numExpected == 0) { @@ -1201,7 +1615,8 @@ std::string GeneratorExpressionContent::EvaluateParameters( return std::string(); } - if (numExpected == -1 && parameters.empty()) + if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters + && parameters.empty()) { reportError(context, this->GetOriginalExpression(), "$<" + identifier + "> expression requires at least one parameter."); @@ -1228,7 +1643,6 @@ GeneratorExpressionContent::~GeneratorExpressionContent() deleteAll(this->IdentifierChildren); typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector; - typedef std::vector<cmGeneratorExpressionToken> TokenVector; std::vector<EvaluatorVector>::const_iterator pit = this->ParamChildren.begin(); const std::vector<EvaluatorVector>::const_iterator pend = diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index ce7ad69bb..218abf160 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -129,6 +129,14 @@ private: cmGeneratorExpressionDAGChecker *dagChecker, std::vector<std::string> ¶meters) const; + std::string ProcessArbitraryContent( + const cmGeneratorExpressionNode *node, + const std::string &identifier, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator + pit) const; + private: std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren; std::vector<std::vector<cmGeneratorExpressionEvaluator*> > ParamChildren; diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx index a619cecd0..e1fb8f1de 100644 --- a/Source/cmGeneratorExpressionParser.cxx +++ b/Source/cmGeneratorExpressionParser.cxx @@ -126,6 +126,9 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator> commaTokens; std::vector<cmGeneratorExpressionToken>::const_iterator colonToken; + + bool emptyParamTermination = false; + if (this->it != this->Tokens.end() && this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) { @@ -133,6 +136,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( parameters.resize(parameters.size() + 1); assert(this->it != this->Tokens.end()); ++this->it; + if(this->it == this->Tokens.end()) + { + emptyParamTermination = true; + } while (this->it != this->Tokens.end() && this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) @@ -141,6 +148,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( parameters.resize(parameters.size() + 1); assert(this->it != this->Tokens.end()); ++this->it; + if(this->it == this->Tokens.end()) + { + emptyParamTermination = true; + } } while (this->it != this->Tokens.end() && this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) @@ -164,6 +175,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( parameters.resize(parameters.size() + 1); assert(this->it != this->Tokens.end()); ++this->it; + if(this->it == this->Tokens.end()) + { + emptyParamTermination = true; + } } while (this->it != this->Tokens.end() && this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) @@ -203,7 +218,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( assert(parameters.size() > commaTokens.size()); for ( ; pit != pend; ++pit, ++commaIt) { - extendResult(result, *pit); + if (!pit->empty() && !emptyParamTermination) + { + extendResult(result, *pit); + } if (commaIt != commaTokens.end()) { extendText(result, *commaIt); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 335ba0f25..62ac2638d 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -48,6 +48,57 @@ const char *cmGeneratorTarget::GetProperty(const char *prop) } //---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir, + const char *config) +{ + std::string config_upper; + if(config && *config) + { + config_upper = cmSystemTools::UpperCase(config); + } + + typedef std::map<std::string, std::vector<std::string> > IncludeCacheType; + IncludeCacheType::iterator iter = + this->SystemIncludesCache.find(config_upper); + + if (iter == this->SystemIncludesCache.end()) + { + std::vector<std::string> result; + for (std::set<cmStdString>::const_iterator + it = this->Target->GetSystemIncludeDirectories().begin(); + it != this->Target->GetSystemIncludeDirectories().end(); ++it) + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", 0, 0); + + cmSystemTools::ExpandListArgument(ge.Parse(*it) + ->Evaluate(this->Makefile, + config, false, this->Target, + &dagChecker), result); + } + for(std::vector<std::string>::iterator li = result.begin(); + li != result.end(); ++li) + { + cmSystemTools::ConvertToUnixSlashes(*li); + } + + IncludeCacheType::value_type entry(config_upper, result); + iter = this->SystemIncludesCache.insert(entry).first; + } + + if (std::find(iter->second.begin(), + iter->second.end(), dir) != iter->second.end()) + { + return true; + } + return false; +} + +//---------------------------------------------------------------------------- bool cmGeneratorTarget::GetPropertyAsBool(const char *prop) { return this->Target->GetPropertyAsBool(prop); @@ -98,6 +149,18 @@ void cmGeneratorTarget::ClassifySources() this->IDLSources.push_back(sf); if(isObjLib) { badObjLib.push_back(sf); } } + else if(ext == "resx") + { + // Build and save the name of the corresponding .h file + // This relationship will be used later when building the project files. + // Both names would have been auto generated from Visual Studio + // where the user supplied the file name and Visual Studio + // appended the suffix. + std::string resx = sf->GetFullPath(); + std::string hFileName = resx.substr(0, resx.find_last_of(".")) + ".h"; + this->ExpectedResxHeaders.insert(hFileName); + this->ResxSources.push_back(sf); + } else if(header.find(sf->GetFullPath().c_str())) { this->HeaderSources.push_back(sf); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index cbcd8a579..dedfa60aa 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -44,11 +44,15 @@ public: std::vector<cmSourceFile*> ObjectSources; std::vector<cmSourceFile*> ExternalObjects; std::vector<cmSourceFile*> IDLSources; + std::vector<cmSourceFile*> ResxSources; + std::string ModuleDefinitionFile; std::map<cmSourceFile const*, std::string> Objects; std::set<cmSourceFile const*> ExplicitObjectName; + std::set<std::string> ExpectedResxHeaders; + /** Full path with trailing slash to the top-level directory holding object files for this target. Includes the build time config name placeholder if needed for the generator. */ @@ -68,10 +72,14 @@ public: /** Get the include directories for this target. */ std::vector<std::string> GetIncludeDirectories(const char *config); + bool IsSystemIncludeDirectory(const char *dir, const char *config); + private: void ClassifySources(); void LookupObjectLibraries(); + std::map<std::string, std::vector<std::string> > SystemIncludesCache; + cmGeneratorTarget(cmGeneratorTarget const&); void operator=(cmGeneratorTarget const&); }; diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx index 8bb54877e..e7ad91a36 100644 --- a/Source/cmGetCMakePropertyCommand.cxx +++ b/Source/cmGetCMakePropertyCommand.cxx @@ -11,6 +11,8 @@ ============================================================================*/ #include "cmGetCMakePropertyCommand.h" +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" #include "cmake.h" // cmGetCMakePropertyCommand diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index fd1ad601f..1d7fefcee 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -58,7 +58,7 @@ bool cmGetFilenameComponentCommand } std::string storeArgs; std::string programArgs; - if (args[2] == "PATH") + if (args[2] == "DIRECTORY" || args[2] == "PATH") { result = cmSystemTools::GetFilenamePath(filename); } diff --git a/Source/cmGetFilenameComponentCommand.h b/Source/cmGetFilenameComponentCommand.h index f294daa0d..09af3325a 100644 --- a/Source/cmGetFilenameComponentCommand.h +++ b/Source/cmGetFilenameComponentCommand.h @@ -64,12 +64,13 @@ public: return " get_filename_component(<VAR> <FileName> <COMP> [CACHE])\n" "Set <VAR> to a component of <FileName>, where <COMP> is one of:\n" - " PATH = Directory without file name\n" + " DIRECTORY = Directory without file name\n" " NAME = File name without directory\n" " EXT = File name longest extension (.b.c from d/a.b.c)\n" " NAME_WE = File name without directory or longest extension\n" " ABSOLUTE = Full path to file\n" " REALPATH = Full path to existing file with symlinks resolved\n" + " PATH = Legacy alias for DIRECTORY (use for CMake <= 2.8.11)\n" "Paths are returned with forward slashes and have no trailing slahes. " "The longest file extension is always considered. " "If the optional CACHE argument is specified, the result variable is " diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 7d3335887..faba7cd35 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -13,6 +13,9 @@ #include "cmake.h" #include "cmTest.h" +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" +#include "cmSourceFile.h" #include "cmPropertyDefinition.h" //---------------------------------------------------------------------------- @@ -285,6 +288,18 @@ bool cmGetPropertyCommand::HandleTargetMode() return false; } + if(this->PropertyName == "ALIASED_TARGET") + { + if(this->Makefile->IsAlias(this->Name.c_str())) + { + if(cmTarget* target = + this->Makefile->FindTargetToUse(this->Name.c_str())) + { + return this->StoreResult(target->GetName()); + } + } + return false; + } if(cmTarget* target = this->Makefile->FindTargetToUse(this->Name.c_str())) { return this->StoreResult(target->GetProperty(this->PropertyName.c_str())); diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index 1947139c9..02f00a508 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -22,17 +22,30 @@ bool cmGetTargetPropertyCommand } std::string var = args[0].c_str(); const char* targetName = args[1].c_str(); + const char *prop = 0; - if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName)) + if(args[2] == "ALIASED_TARGET") { - cmTarget& target = *tgt; - const char *prop = target.GetProperty(args[2].c_str()); - if (prop) + if(this->Makefile->IsAlias(targetName)) { - this->Makefile->AddDefinition(var.c_str(), prop); - return true; + if(cmTarget* target = + this->Makefile->FindTargetToUse(targetName)) + { + prop = target->GetName(); + } } } + else if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName)) + { + cmTarget& target = *tgt; + prop = target.GetProperty(args[2].c_str()); + } + + if (prop) + { + this->Makefile->AddDefinition(var.c_str(), prop); + return true; + } this->Makefile->AddDefinition(var.c_str(), (var+"-NOTFOUND").c_str()); return true; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index df1433105..f297c4abb 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -26,6 +26,7 @@ #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorExpressionEvaluationFile.h" #include <cmsys/Directory.hxx> @@ -69,6 +70,13 @@ cmGlobalGenerator::~cmGlobalGenerator() { delete this->LocalGenerators[i]; } + for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator + li = this->EvaluationFiles.begin(); + li != this->EvaluationFiles.end(); + ++li) + { + delete *li; + } this->LocalGenerators.clear(); if (this->ExtraGenerator) @@ -407,7 +415,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, { if(!mf->ReadListFile(0,fpath.c_str())) { - cmSystemTools::Error("Could not find cmake module file:", + cmSystemTools::Error("Could not find cmake module file: ", fpath.c_str()); } // if this file was found then the language was already determined @@ -423,7 +431,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, { if (this->CMakeInstance->GetIsInTryCompile()) { - cmSystemTools::Error("This should not have happen. " + cmSystemTools::Error("This should not have happened. " "If you see this message, you are probably " "using a broken CMakeLists.txt file or a " "problematic release of CMake"); @@ -437,7 +445,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, mf->GetModulesFile(determineCompiler.c_str()); if(!mf->ReadListFile(0,determineFile.c_str())) { - cmSystemTools::Error("Could not find cmake module file:", + cmSystemTools::Error("Could not find cmake module file: ", determineFile.c_str()); } needTestLanguage[lang] = true; @@ -471,7 +479,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, fpath += "Compiler.cmake"; if(!mf->ReadListFile(0,fpath.c_str())) { - cmSystemTools::Error("Could not find cmake module file:", + cmSystemTools::Error("Could not find cmake module file: ", fpath.c_str()); } this->SetLanguageEnabledFlag(lang, mf); @@ -490,7 +498,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake"); if(!mf->ReadListFile(0,fpath.c_str())) { - cmSystemTools::Error("Could not find cmake module file:", + cmSystemTools::Error("Could not find cmake module file: ", fpath.c_str()); } } @@ -516,12 +524,12 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, std::string informationFile = mf->GetModulesFile(fpath.c_str()); if (informationFile.empty()) { - cmSystemTools::Error("Could not find cmake module file:", + cmSystemTools::Error("Could not find cmake module file: ", fpath.c_str()); } else if(!mf->ReadListFile(0, informationFile.c_str())) { - cmSystemTools::Error("Could not process cmake module file:", + cmSystemTools::Error("Could not process cmake module file: ", informationFile.c_str()); } } @@ -560,7 +568,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, std::string ifpath = mf->GetModulesFile(testLang.c_str()); if(!mf->ReadListFile(0,ifpath.c_str())) { - cmSystemTools::Error("Could not find cmake module file:", + cmSystemTools::Error("Could not find cmake module file: ", ifpath.c_str()); } std::string compilerWorks = "CMAKE_"; @@ -840,6 +848,14 @@ void cmGlobalGenerator::Configure() delete this->LocalGenerators[i]; } this->LocalGenerators.clear(); + for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator + li = this->EvaluationFiles.begin(); + li != this->EvaluationFiles.end(); + ++li) + { + delete *li; + } + this->EvaluationFiles.clear(); this->TargetDependencies.clear(); this->TotalTargets.clear(); this->ImportedTargets.clear(); @@ -884,12 +900,28 @@ void cmGlobalGenerator::Configure() if ( this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE) { - const char* msg = "Configuring done"; + cmOStringStream msg; if(cmSystemTools::GetErrorOccuredFlag()) { - msg = "Configuring incomplete, errors occurred!"; + msg << "Configuring incomplete, errors occurred!"; + const char* logs[] = {"CMakeOutput.log", "CMakeError.log", 0}; + for(const char** log = logs; *log; ++log) + { + std::string f = this->CMakeInstance->GetHomeOutputDirectory(); + f += this->CMakeInstance->GetCMakeFilesDirectory(); + f += "/"; + f += *log; + if(cmSystemTools::FileExists(f.c_str())) + { + msg << "\nSee also \"" << f << "\"."; + } + } } - this->CMakeInstance->UpdateProgress(msg, -1); + else + { + msg << "Configuring done"; + } + this->CMakeInstance->UpdateProgress(msg.str().c_str(), -1); } } @@ -932,6 +964,8 @@ void cmGlobalGenerator::Generate() return; } + this->FinalizeTargetCompileDefinitions(); + // Iterate through all targets and set up automoc for those which have // the AUTOMOC property set this->CreateAutomocTargets(); @@ -955,7 +989,7 @@ void cmGlobalGenerator::Generate() for ( tit = targets->begin(); tit != targets->end(); ++ tit ) { - tit->second.AppendBuildInterfaceIncludes(); + tit->second.AppendBuildInterfaceIncludes(); } } @@ -981,6 +1015,8 @@ void cmGlobalGenerator::Generate() // Create per-target generator information. this->CreateGeneratorTargets(); + this->ProcessEvaluationFiles(); + // Compute the inter-target dependencies. if(!this->ComputeTargetDepends()) { @@ -991,6 +1027,17 @@ void cmGlobalGenerator::Generate() // it builds by default. this->FillLocalGeneratorToTargetMap(); + for (i = 0; i < this->LocalGenerators.size(); ++i) + { + cmMakefile* mf = this->LocalGenerators[i]->GetMakefile(); + cmTargets* targets = &(mf->GetTargets()); + for ( cmTargets::iterator it = targets->begin(); + it != targets->end(); ++ it ) + { + it->second.FinalizeSystemIncludeDirectories(); + } + } + // Generate project files for (i = 0; i < this->LocalGenerators.size(); ++i) { @@ -1051,6 +1098,7 @@ bool cmGlobalGenerator::CheckTargets() target.GetType() == cmTarget::STATIC_LIBRARY || target.GetType() == cmTarget::SHARED_LIBRARY || target.GetType() == cmTarget::MODULE_LIBRARY || + target.GetType() == cmTarget::OBJECT_LIBRARY || target.GetType() == cmTarget::UTILITY) { if(!target.FindSourceFiles()) @@ -1103,16 +1151,15 @@ void cmGlobalGenerator::CreateAutomocTargets() } //---------------------------------------------------------------------------- -void cmGlobalGenerator::CreateGeneratorTargets() +void cmGlobalGenerator::FinalizeTargetCompileDefinitions() { // Construct per-target generator information. for(unsigned int i=0; i < this->LocalGenerators.size(); ++i) { - cmGeneratorTargetsType generatorTargets; - cmMakefile *mf = this->LocalGenerators[i]->GetMakefile(); - const char *noconfig_compile_definitions = - mf->GetProperty("COMPILE_DEFINITIONS"); + + const std::vector<cmValueWithOrigin> noconfig_compile_definitions = + mf->GetCompileDefinitionsEntries(); std::vector<std::string> configs; mf->GetConfigurations(configs); @@ -1123,8 +1170,13 @@ void cmGlobalGenerator::CreateGeneratorTargets() { cmTarget* t = &ti->second; - { - t->AppendProperty("COMPILE_DEFINITIONS", noconfig_compile_definitions); + for (std::vector<cmValueWithOrigin>::const_iterator it + = noconfig_compile_definitions.begin(); + it != noconfig_compile_definitions.end(); ++it) + { + t->InsertCompileDefinition(*it); + } + for(std::vector<std::string>::const_iterator ci = configs.begin(); ci != configs.end(); ++ci) { @@ -1134,7 +1186,24 @@ void cmGlobalGenerator::CreateGeneratorTargets() mf->GetProperty(defPropName.c_str())); } } + } +} +//---------------------------------------------------------------------------- +void cmGlobalGenerator::CreateGeneratorTargets() +{ + // Construct per-target generator information. + for(unsigned int i=0; i < this->LocalGenerators.size(); ++i) + { + cmGeneratorTargetsType generatorTargets; + + cmMakefile *mf = this->LocalGenerators[i]->GetMakefile(); + + cmTargets& targets = mf->GetTargets(); + for(cmTargets::iterator ti = targets.begin(); + ti != targets.end(); ++ti) + { + cmTarget* t = &ti->second; cmGeneratorTarget* gt = new cmGeneratorTarget(t); this->GeneratorTargets[t] = gt; this->ComputeTargetObjects(gt); @@ -1340,11 +1409,13 @@ int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir, std::string cmGlobalGenerator ::GenerateBuildCommand(const char* makeProgram, const char *projectName, - const char* additionalOptions, const char *targetName, - const char* config, bool ignoreErrors, bool) + const char *projectDir, const char* additionalOptions, + const char *targetName, const char* config, + bool ignoreErrors, bool) { - // Project name and config are not used yet. + // Project name & dir and config are not used yet. (void)projectName; + (void)projectDir; (void)config; std::string makeCommand = @@ -1411,7 +1482,7 @@ int cmGlobalGenerator::Build( if (clean) { std::string cleanCommand = - this->GenerateBuildCommand(makeCommandCSTR, projectName, + this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir, 0, "clean", config, false, fast); if(output) { @@ -1443,7 +1514,7 @@ int cmGlobalGenerator::Build( // now build std::string makeCommand = - this->GenerateBuildCommand(makeCommandCSTR, projectName, + this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir, extraOptions, target, config, false, fast); if(output) @@ -1723,10 +1794,22 @@ cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir) return 0; } +//---------------------------------------------------------------------------- +void cmGlobalGenerator::AddAlias(const char *name, cmTarget *tgt) +{ + this->AliasTargets[name] = tgt; +} + +//---------------------------------------------------------------------------- +bool cmGlobalGenerator::IsAlias(const char *name) +{ + return this->AliasTargets.find(name) != this->AliasTargets.end(); +} //---------------------------------------------------------------------------- cmTarget* -cmGlobalGenerator::FindTarget(const char* project, const char* name) +cmGlobalGenerator::FindTarget(const char* project, const char* name, + bool excludeAliases) { // if project specific if(project) @@ -1734,7 +1817,8 @@ cmGlobalGenerator::FindTarget(const char* project, const char* name) std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project]; for(unsigned int i = 0; i < gens->size(); ++i) { - cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name); + cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name, + excludeAliases); if(ret) { return ret; @@ -1744,6 +1828,15 @@ cmGlobalGenerator::FindTarget(const char* project, const char* name) // if all projects/directories else { + if (!excludeAliases) + { + std::map<cmStdString, cmTarget*>::iterator ai + = this->AliasTargets.find(name); + if (ai != this->AliasTargets.end()) + { + return ai->second; + } + } std::map<cmStdString,cmTarget *>::iterator i = this->TotalTargets.find ( name ); if ( i != this->TotalTargets.end() ) @@ -2558,3 +2651,44 @@ std::string cmGlobalGenerator::EscapeJSON(const std::string& s) { } return result; } + +//---------------------------------------------------------------------------- +void cmGlobalGenerator::AddEvaluationFile(const std::string &inputFile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputExpr, + cmMakefile *makefile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, + bool inputIsContent) +{ + this->EvaluationFiles.push_back( + new cmGeneratorExpressionEvaluationFile(inputFile, outputExpr, + makefile, condition, + inputIsContent)); +} + +//---------------------------------------------------------------------------- +void cmGlobalGenerator::ProcessEvaluationFiles() +{ + std::set<std::string> generatedFiles; + for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator + li = this->EvaluationFiles.begin(); + li != this->EvaluationFiles.end(); + ++li) + { + (*li)->Generate(); + if (cmSystemTools::GetFatalErrorOccured()) + { + return; + } + std::vector<std::string> files = (*li)->GetFiles(); + for(std::vector<std::string>::const_iterator fi = files.begin(); + fi != files.end(); ++fi) + { + if (!generatedFiles.insert(*fi).second) + { + cmSystemTools::Error("File to be generated by multiple different " + "commands: ", fi->c_str()); + return; + } + } + } +} diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 11616e0d0..80916ae59 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -20,9 +20,11 @@ #include "cmSystemTools.h" // for cmSystemTools::OutputOption #include "cmExportSetMap.h" // For cmExportSetMap #include "cmGeneratorTarget.h" +#include "cmGeneratorExpression.h" class cmake; class cmGeneratorTarget; +class cmGeneratorExpressionEvaluationFile; class cmMakefile; class cmLocalGenerator; class cmExternalMakefileProjectGenerator; @@ -121,9 +123,10 @@ public: virtual std::string GenerateBuildCommand( const char* makeProgram, - const char *projectName, const char* additionalOptions, - const char *targetName, - const char* config, bool ignoreErrors, bool fast); + const char *projectName, const char *projectDir, + const char* additionalOptions, + const char *targetName, const char* config, + bool ignoreErrors, bool fast); ///! Set the CMake instance @@ -193,7 +196,11 @@ public: void FindMakeProgram(cmMakefile*); ///! Find a target by name by searching the local generators. - cmTarget* FindTarget(const char* project, const char* name); + cmTarget* FindTarget(const char* project, const char* name, + bool excludeAliases = false); + + void AddAlias(const char *name, cmTarget *tgt); + bool IsAlias(const char *name); /** Determine if a name resolves to a framework on disk or a built target that is a framework. */ @@ -278,6 +285,14 @@ public: static std::string EscapeJSON(const std::string& s); + void AddEvaluationFile(const std::string &inputFile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName, + cmMakefile *makefile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> condition, + bool inputIsContent); + + void ProcessEvaluationFiles(); + protected: typedef std::vector<cmLocalGenerator*> GeneratorVector; // for a project collect all its targets by following depend @@ -336,7 +351,9 @@ protected: // All targets in the entire project. std::map<cmStdString,cmTarget *> TotalTargets; + std::map<cmStdString,cmTarget *> AliasTargets; std::map<cmStdString,cmTarget *> ImportedTargets; + std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles; virtual const char* GetPredefinedTargetsFolder(); virtual bool UseFolderProperty(); @@ -365,6 +382,7 @@ private: void WriteSummary(); void WriteSummary(cmTarget* target); + void FinalizeTargetCompileDefinitions(); cmExternalMakefileProjectGenerator* ExtraGenerator; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index fa277b1d1..1953546de 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -10,11 +10,12 @@ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ +#include "cmGeneratedFileStream.h" +#include "cmGeneratorExpressionEvaluationFile.h" +#include "cmGeneratorTarget.h" #include "cmGlobalNinjaGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" -#include "cmGeneratedFileStream.h" -#include "cmGeneratorTarget.h" #include "cmVersion.h" #include <algorithm> @@ -140,8 +141,15 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, for(cmNinjaDeps::const_iterator i = explicitDeps.begin(); i != explicitDeps.end(); ++i) + { arguments << " " << EncodeIdent(EncodePath(*i), os); + //we need to track every dependency that comes in, since we are trying + //to find dependencies that are side effects of build commands + // + this->CombinedBuildExplicitDependencies.insert( EncodePath(*i) ); + } + // Write implicit dependencies. if(!implicitDeps.empty()) { @@ -170,7 +178,10 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, build << "build"; for(cmNinjaDeps::const_iterator i = outputs.begin(); i != outputs.end(); ++i) + { build << " " << EncodeIdent(EncodePath(*i), os); + this->CombinedBuildOutputs.insert( EncodePath(*i) ); + } build << ":"; // Write the rule. @@ -208,14 +219,14 @@ void cmGlobalNinjaGenerator::WritePhonyBuild(std::ostream& os, const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables) { - cmGlobalNinjaGenerator::WriteBuild(os, - comment, - "phony", - outputs, - explicitDeps, - implicitDeps, - orderOnlyDeps, - variables); + this->WriteBuild(os, + comment, + "phony", + outputs, + explicitDeps, + implicitDeps, + orderOnlyDeps, + variables); } void cmGlobalNinjaGenerator::AddCustomCommandRule() @@ -251,14 +262,14 @@ cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command, vars["COMMAND"] = cmd; vars["DESC"] = EncodeLiteral(description); - cmGlobalNinjaGenerator::WriteBuild(*this->BuildFileStream, - comment, - "CUSTOM_COMMAND", - outputs, - deps, - cmNinjaDeps(), - orderOnlyDeps, - vars); + this->WriteBuild(*this->BuildFileStream, + comment, + "CUSTOM_COMMAND", + outputs, + deps, + cmNinjaDeps(), + orderOnlyDeps, + vars); } void @@ -293,14 +304,14 @@ cmGlobalNinjaGenerator::WriteMacOSXContentBuild(const std::string& input, deps.push_back(input); cmNinjaVars vars; - cmGlobalNinjaGenerator::WriteBuild(*this->BuildFileStream, - "", - "COPY_OSX_CONTENT", - outputs, - deps, - cmNinjaDeps(), - cmNinjaDeps(), - cmNinjaVars()); + this->WriteBuild(*this->BuildFileStream, + "", + "COPY_OSX_CONTENT", + outputs, + deps, + cmNinjaDeps(), + cmNinjaDeps(), + cmNinjaVars()); } void cmGlobalNinjaGenerator::WriteRule(std::ostream& os, @@ -478,6 +489,7 @@ void cmGlobalNinjaGenerator::Generate() this->WriteAssumedSourceDependencies(); this->WriteTargetAliases(*this->BuildFileStream); + this->WriteUnknownExplicitDependencies(*this->BuildFileStream); this->WriteBuiltinTargets(*this->BuildFileStream); if (cmSystemTools::GetErrorOccuredFlag()) { @@ -523,14 +535,16 @@ bool cmGlobalNinjaGenerator::UsingMinGW = false; std::string cmGlobalNinjaGenerator ::GenerateBuildCommand(const char* makeProgram, const char* projectName, + const char* projectDir, const char* additionalOptions, const char* targetName, const char* config, bool ignoreErrors, bool fast) { - // Project name and config are not used yet. + // Project name & dir and config are not used yet. (void)projectName; + (void)projectDir; (void)config; // Ninja does not have -i equivalent option yet. (void)ignoreErrors; @@ -810,13 +824,19 @@ cmGlobalNinjaGenerator cmLocalNinjaGenerator *ng = static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]); + // for frameworks, we want the real name, not smple name + // frameworks always appear versioned, and the build.ninja + // will always attempt to manage symbolic links instead + // of letting cmOSXBundleGenerator do it. + bool realname = target->IsFrameworkOnApple(); + switch (target->GetType()) { case cmTarget::EXECUTABLE: case cmTarget::SHARED_LIBRARY: case cmTarget::STATIC_LIBRARY: case cmTarget::MODULE_LIBRARY: outputs.push_back(ng->ConvertToNinjaPath( - target->GetFullPath(configName).c_str())); + target->GetFullPath(configName, false, realname).c_str())); break; case cmTarget::OBJECT_LIBRARY: @@ -885,7 +905,7 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); os << "# Target aliases.\n\n"; - for (TargetAliasMap::iterator i = TargetAliases.begin(); + for (TargetAliasMap::const_iterator i = TargetAliases.begin(); i != TargetAliases.end(); ++i) { // Don't write ambiguous aliases. if (!i->second) @@ -894,13 +914,128 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) cmNinjaDeps deps; this->AppendTargetOutputs(i->second, deps); - cmGlobalNinjaGenerator::WritePhonyBuild(os, - "", - cmNinjaDeps(1, i->first), - deps); + this->WritePhonyBuild(os, + "", + cmNinjaDeps(1, i->first), + deps); } } +void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) +{ + //now write out the unknown explicit dependencies. + + //union the configured files, evaluations files and the CombinedBuildOutputs, + //and then difference with CombinedExplicitDependencies to find the explicit + //dependencies that we have no rule for + + cmGlobalNinjaGenerator::WriteDivider(os); + os << "# Unknown Build Time Dependencies.\n" + << "# Tell Ninja that they may appear as side effects of build rules\n" + << "# otherwise ordered by order-only dependencies.\n\n"; + + //get the list of files that cmake itself has generated as a + //product of configuration. + cmLocalNinjaGenerator *ng = + static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]); + + std::set<std::string> knownDependencies; + for (std::vector<cmLocalGenerator *>::const_iterator i = + this->LocalGenerators.begin(); i != this->LocalGenerators.end(); ++i) + { + //get the vector of files created by this makefile and convert them + //to ninja paths, which are all relative in respect to the build directory + const std::vector<std::string>& files = + (*i)->GetMakefile()->GetOutputFiles(); + typedef std::vector<std::string>::const_iterator vect_it; + for(vect_it j = files.begin(); j != files.end(); ++j) + { + knownDependencies.insert( ng->ConvertToNinjaPath( j->c_str() ) ); + } + } + + for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator + li = this->EvaluationFiles.begin(); + li != this->EvaluationFiles.end(); + ++li) + { + //get all the files created by generator expressions and convert them + //to ninja paths + std::vector<std::string> files = (*li)->GetFiles(); + typedef std::vector<std::string>::const_iterator vect_it; + for(vect_it j = files.begin(); j != files.end(); ++j) + { + knownDependencies.insert( ng->ConvertToNinjaPath( j->c_str() ) ); + } + } + + for(TargetAliasMap::const_iterator i= this->TargetAliases.begin(); + i != this->TargetAliases.end(); + ++i) + { + knownDependencies.insert( ng->ConvertToNinjaPath(i->first.c_str()) ); + } + + //remove all source files we know will exist. + typedef std::map<std::string, std::set<std::string> >::const_iterator map_it; + for(map_it i = this->AssumedSourceDependencies.begin(); + i != this->AssumedSourceDependencies.end(); + ++i) + { + knownDependencies.insert( ng->ConvertToNinjaPath(i->first.c_str()) ); + } + + //insert outputs from all WirteBuild commands + for(std::set<std::string>::iterator i = this->CombinedBuildOutputs.begin(); + i != this->CombinedBuildOutputs.end(); ++i) + { + //these paths have already be encoded when added to CombinedBuildOutputs + knownDependencies.insert(*i); + } + + //after we have combined the data into knownDependencies we have no need + //to keep this data around + this->CombinedBuildOutputs.clear(); + + //now we difference with CombinedBuildExplicitDependencies to find + //the list of items we know nothing about. + //We have encoded all the paths in CombinedBuildExplicitDependencies + //and knownDependencies so no matter if unix or windows paths they + //should all match now. + + std::vector<std::string> unkownExplicitDepends; + this->CombinedBuildExplicitDependencies.erase("all"); + + std::set_difference(this->CombinedBuildExplicitDependencies.begin(), + this->CombinedBuildExplicitDependencies.end(), + knownDependencies.begin(), + knownDependencies.end(), + std::back_inserter(unkownExplicitDepends)); + + + std::string const rootBuildDirectory = + this->GetCMakeInstance()->GetHomeOutputDirectory(); + for (std::vector<std::string>::const_iterator + i = unkownExplicitDepends.begin(); + i != unkownExplicitDepends.end(); + ++i) + { + //verify the file is in the build directory + std::string const absDepPath = cmSystemTools::CollapseFullPath( + i->c_str(), rootBuildDirectory.c_str()); + bool const inBuildDir = cmSystemTools::IsSubDirectory(absDepPath.c_str(), + rootBuildDirectory.c_str()); + if(inBuildDir) + { + cmNinjaDeps deps(1,*i); + this->WritePhonyBuild(os, + "", + deps, + deps); + } + } +} + void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os) { // Write headers. @@ -918,10 +1053,10 @@ void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os) cmNinjaDeps outputs; outputs.push_back("all"); - cmGlobalNinjaGenerator::WritePhonyBuild(os, - "The main all target.", - outputs, - this->AllDependencies); + this->WritePhonyBuild(os, + "The main all target.", + outputs, + this->AllDependencies); cmGlobalNinjaGenerator::WriteDefault(os, outputs, @@ -965,19 +1100,19 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) implicitDeps.end()); implicitDeps.push_back("CMakeCache.txt"); - WriteBuild(os, - "Re-run CMake if any of its inputs changed.", - "RERUN_CMAKE", - /*outputs=*/ cmNinjaDeps(1, NINJA_BUILD_FILE), - /*explicitDeps=*/ cmNinjaDeps(), - implicitDeps, - /*orderOnlyDeps=*/ cmNinjaDeps(), - /*variables=*/ cmNinjaVars()); - - WritePhonyBuild(os, - "A missing CMake input file is not an error.", - implicitDeps, - cmNinjaDeps()); + this->WriteBuild(os, + "Re-run CMake if any of its inputs changed.", + "RERUN_CMAKE", + /*outputs=*/ cmNinjaDeps(1, NINJA_BUILD_FILE), + /*explicitDeps=*/ cmNinjaDeps(), + implicitDeps, + /*orderOnlyDeps=*/ cmNinjaDeps(), + /*variables=*/ cmNinjaVars()); + + this->WritePhonyBuild(os, + "A missing CMake input file is not an error.", + implicitDeps, + cmNinjaDeps()); } std::string cmGlobalNinjaGenerator::ninjaCmd() const diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index c3df7d935..e046c7c96 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -77,27 +77,27 @@ public: * It also writes the variables bound to this build statement. * @warning no escaping of any kind is done here. */ - static void WriteBuild(std::ostream& os, - const std::string& comment, - const std::string& rule, - const cmNinjaDeps& outputs, - const cmNinjaDeps& explicitDeps, - const cmNinjaDeps& implicitDeps, - const cmNinjaDeps& orderOnlyDeps, - const cmNinjaVars& variables, - const std::string& rspfile = std::string(), - int cmdLineLimit = -1); + void WriteBuild(std::ostream& os, + const std::string& comment, + const std::string& rule, + const cmNinjaDeps& outputs, + const cmNinjaDeps& explicitDeps, + const cmNinjaDeps& implicitDeps, + const cmNinjaDeps& orderOnlyDeps, + const cmNinjaVars& variables, + const std::string& rspfile = std::string(), + int cmdLineLimit = -1); /** * Helper to write a build statement with the special 'phony' rule. */ - static void WritePhonyBuild(std::ostream& os, - const std::string& comment, - const cmNinjaDeps& outputs, - const cmNinjaDeps& explicitDeps, - const cmNinjaDeps& implicitDeps = cmNinjaDeps(), - const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps(), - const cmNinjaVars& variables = cmNinjaVars()); + void WritePhonyBuild(std::ostream& os, + const std::string& comment, + const cmNinjaDeps& outputs, + const cmNinjaDeps& explicitDeps, + const cmNinjaDeps& implicitDeps = cmNinjaDeps(), + const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps(), + const cmNinjaVars& variables = cmNinjaVars()); void WriteCustomCommandBuild(const std::string& command, const std::string& description, @@ -191,6 +191,7 @@ public: /// Overloaded methods. @see cmGlobalGenerator::GenerateBuildCommand() virtual std::string GenerateBuildCommand(const char* makeProgram, const char* projectName, + const char* projectDir, const char* additionalOptions, const char* targetName, const char* config, @@ -320,6 +321,7 @@ private: void WriteAssumedSourceDependencies(); void WriteTargetAliases(std::ostream& os); + void WriteUnknownExplicitDependencies(std::ostream& os); void WriteBuiltinTargets(std::ostream& os); void WriteTargetAll(std::ostream& os); @@ -357,6 +359,12 @@ private: /// The set of custom command outputs we have seen. std::set<std::string> CustomCommandOutputs; + //The combined explicit dependencies of all build commands that the global + //generator has issued. When combined with CombinedBuildOutputs it allows + //us to detect the set of explicit dependencies that have + std::set<std::string> CombinedBuildExplicitDependencies; + std::set<std::string> CombinedBuildOutputs; + /// The mapping from source file to assumed dependencies. std::map<std::string, std::set<std::string> > AssumedSourceDependencies; diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index e26cca940..88cd6e5f8 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -517,11 +517,13 @@ cmGlobalUnixMakefileGenerator3 std::string cmGlobalUnixMakefileGenerator3 ::GenerateBuildCommand(const char* makeProgram, const char *projectName, - const char* additionalOptions, const char *targetName, - const char* config, bool ignoreErrors, bool fast) + const char *projectDir, const char* additionalOptions, + const char *targetName, const char* config, + bool ignoreErrors, bool fast) { - // Project name and config are not used yet. + // Project name & dir and config are not used yet. (void)projectName; + (void)projectDir; (void)config; std::string makeCommand = diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 385cdc4a1..5e9dce3a6 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -107,7 +107,8 @@ public: // change the build command for speed virtual std::string GenerateBuildCommand (const char* makeProgram, - const char *projectName, const char* additionalOptions, + const char *projectName, const char *projectDir, + const char* additionalOptions, const char *targetName, const char* config, bool ignoreErrors, bool fast); diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index ee7c56fc6..b2a337cc6 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -14,6 +14,8 @@ #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" #include "cmSourceFile.h" +#include "cmVisualStudioSlnData.h" +#include "cmVisualStudioSlnParser.h" #include "cmake.h" static const char vs10Win32generatorName[] = "Visual Studio 10"; @@ -28,17 +30,17 @@ public: if(!strcmp(name, vs10Win32generatorName)) { return new cmGlobalVisualStudio10Generator( - vs10Win32generatorName, NULL, NULL); + name, NULL, NULL); } if(!strcmp(name, vs10Win64generatorName)) { return new cmGlobalVisualStudio10Generator( - vs10Win64generatorName, "x64", "CMAKE_FORCE_WIN64"); + name, "x64", "CMAKE_FORCE_WIN64"); } if(!strcmp(name, vs10IA64generatorName)) { return new cmGlobalVisualStudio10Generator( - vs10IA64generatorName, "Itanium", "CMAKE_FORCE_IA64"); + name, "Itanium", "CMAKE_FORCE_IA64"); } return 0; } @@ -67,9 +69,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory() //---------------------------------------------------------------------------- cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( - const char* name, const char* architectureId, + const char* name, const char* platformName, const char* additionalPlatformDefinition) - : cmGlobalVisualStudio8Generator(name, architectureId, + : cmGlobalVisualStudio8Generator(name, platformName, additionalPlatformDefinition) { this->FindMakeProgramFile = "CMakeVS10FindMake.cmake"; @@ -77,6 +79,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( this->ExpressEdition = cmSystemTools::ReadRegistryValue( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;" "ProductDir", vc10Express, cmSystemTools::KeyWOW64_32); + this->MasmEnabled = false; } //---------------------------------------------------------------------------- @@ -159,13 +162,23 @@ void cmGlobalVisualStudio10Generator ::EnableLanguage(std::vector<std::string>const & lang, cmMakefile *mf, bool optional) { - if(this->ArchitectureId == "Itanium" || this->ArchitectureId == "x64") + if(this->PlatformName == "Itanium" || this->PlatformName == "x64") { if(this->IsExpressEdition() && !this->Find64BitTools(mf)) { return; } } + + for(std::vector<std::string>::const_iterator it = lang.begin(); + it != lang.end(); ++it) + { + if(*it == "ASM_MASM") + { + this->MasmEnabled = true; + } + } + cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional); } @@ -215,7 +228,7 @@ std::string cmGlobalVisualStudio10Generator::GetUserMacrosRegKeyBase() std::string cmGlobalVisualStudio10Generator ::GenerateBuildCommand(const char* makeProgram, - const char *projectName, + const char *projectName, const char *projectDir, const char* additionalOptions, const char *targetName, const char* config, bool ignoreErrors, bool fast) { @@ -230,7 +243,8 @@ std::string cmGlobalVisualStudio10Generator lowerCaseCommand.find("VCExpress") != std::string::npos) { return cmGlobalVisualStudio7Generator::GenerateBuildCommand(makeProgram, - projectName, additionalOptions, targetName, config, ignoreErrors, fast); + projectName, projectDir, additionalOptions, targetName, config, + ignoreErrors, fast); } // Otherwise, assume MSBuild command line, and construct accordingly. @@ -258,9 +272,38 @@ std::string cmGlobalVisualStudio10Generator } else { + std::string targetProject(targetName); + targetProject += ".vcxproj"; + if (targetProject.find('/') == std::string::npos) + { + // it might be in a subdir + cmVisualStudioSlnParser parser; + cmSlnData slnData; + std::string slnFile; + if (projectDir && *projectDir) + { + slnFile = projectDir; + slnFile += '/'; + slnFile += projectName; + } + else + { + slnFile = projectName; + } + if (parser.ParseFile(slnFile + ".sln", slnData, + cmVisualStudioSlnParser::DataGroupProjects)) + { + if (cmSlnProjectEntry const* proj = + slnData.GetProjectByName(targetName)) + { + targetProject = proj->GetRelativePath(); + cmSystemTools::ConvertToUnixSlashes(targetProject); + } + } + } + makeCommand += " "; + makeCommand += targetProject; makeCommand += " "; - makeCommand += targetName; - makeCommand += ".vcxproj "; } makeCommand += "/p:Configuration="; if(config && strlen(config)) diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 5926e0f21..31e122efe 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -25,14 +25,14 @@ class cmGlobalVisualStudio10Generator : { public: cmGlobalVisualStudio10Generator(const char* name, - const char* architectureId, const char* additionalPlatformDefinition); + const char* platformName, const char* additionalPlatformDefinition); static cmGlobalGeneratorFactory* NewFactory(); virtual bool SetGeneratorToolset(std::string const& ts); virtual std::string GenerateBuildCommand(const char* makeProgram, - const char *projectName, + const char *projectName, const char *projectDir, const char* additionalOptions, const char *targetName, const char* config, bool ignoreErrors, bool); @@ -54,6 +54,9 @@ public: /** Is the installed VS an Express edition? */ bool IsExpressEdition() const { return this->ExpressEdition; } + /** Is the Microsoft Assembler enabled? */ + bool IsMasmEnabled() const { return this->MasmEnabled; } + /** The toolset name for the target platform. */ const char* GetPlatformToolset(); @@ -78,11 +81,15 @@ public: void PathTooLong(cmTarget* target, cmSourceFile* sf, std::string const& sfRel); + + virtual const char* GetToolsVersion() { return "4.0"; } + protected: virtual const char* GetIDEVersion() { return "10.0"; } std::string PlatformToolset; bool ExpressEdition; + bool MasmEnabled; bool UseFolderProperty(); diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index 624d01d69..8ae733165 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -13,31 +13,56 @@ #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" -static const char vs11Win32generatorName[] = "Visual Studio 11"; -static const char vs11Win64generatorName[] = "Visual Studio 11 Win64"; -static const char vs11ARMgeneratorName[] = "Visual Studio 11 ARM"; +static const char vs11generatorName[] = "Visual Studio 11"; class cmGlobalVisualStudio11Generator::Factory : public cmGlobalGeneratorFactory { public: virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const { - if(!strcmp(name, vs11Win32generatorName)) + if(strstr(name, vs11generatorName) != name) + { + return 0; + } + + const char* p = name + sizeof(vs11generatorName) - 1; + if(p[0] == '\0') { return new cmGlobalVisualStudio11Generator( - vs11Win32generatorName, NULL, NULL); + name, NULL, NULL); + } + + if(p[0] != ' ') + { + return 0; } - if(!strcmp(name, vs11Win64generatorName)) + + ++p; + + if(!strcmp(p, "ARM")) { return new cmGlobalVisualStudio11Generator( - vs11Win64generatorName, "x64", "CMAKE_FORCE_WIN64"); + name, "ARM", NULL); } - if(!strcmp(name, vs11ARMgeneratorName)) + + if(!strcmp(p, "Win64")) { return new cmGlobalVisualStudio11Generator( - vs11ARMgeneratorName, "ARM", NULL); + name, "x64", "CMAKE_FORCE_WIN64"); } - return 0; + + std::set<std::string> installedSDKs = + cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs(); + + if(installedSDKs.find(p) == installedSDKs.end()) + { + return 0; + } + + cmGlobalVisualStudio11Generator* ret = + new cmGlobalVisualStudio11Generator(name, p, NULL); + ret->WindowsCEVersion = "8.00"; + return ret; } virtual void GetDocumentation(cmDocumentationEntry& entry) const { @@ -51,9 +76,18 @@ public: } virtual void GetGenerators(std::vector<std::string>& names) const { - names.push_back(vs11Win32generatorName); - names.push_back(vs11Win64generatorName); - names.push_back(vs11ARMgeneratorName); } + names.push_back(vs11generatorName); + names.push_back(vs11generatorName + std::string(" ARM")); + names.push_back(vs11generatorName + std::string(" Win64")); + + std::set<std::string> installedSDKs = + cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs(); + for(std::set<std::string>::const_iterator i = + installedSDKs.begin(); i != installedSDKs.end(); ++i) + { + names.push_back("Visual Studio 11 " + *i); + } + } }; //---------------------------------------------------------------------------- @@ -64,9 +98,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory() //---------------------------------------------------------------------------- cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator( - const char* name, const char* architectureId, + const char* name, const char* platformName, const char* additionalPlatformDefinition) - : cmGlobalVisualStudio10Generator(name, architectureId, + : cmGlobalVisualStudio10Generator(name, platformName, additionalPlatformDefinition) { this->FindMakeProgramFile = "CMakeVS11FindMake.cmake"; @@ -109,3 +143,36 @@ bool cmGlobalVisualStudio11Generator::UseFolderProperty() // Express editions in VS10 and earlier, but they are in VS11 Express. return cmGlobalVisualStudio8Generator::UseFolderProperty(); } + +//---------------------------------------------------------------------------- +std::set<std::string> +cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs() +{ + const char sdksKey[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" + "Windows CE Tools\\SDKs"; + + std::vector<std::string> subkeys; + cmSystemTools::GetRegistrySubKeys(sdksKey, subkeys, + cmSystemTools::KeyWOW64_32); + + std::set<std::string> ret; + for(std::vector<std::string>::const_iterator i = + subkeys.begin(); i != subkeys.end(); ++i) + { + std::string key = sdksKey; + key += '\\'; + key += *i; + key += ';'; + + std::string path; + if(cmSystemTools::ReadRegistryValue(key.c_str(), + path, + cmSystemTools::KeyWOW64_32) && + !path.empty()) + { + ret.insert(*i); + } + } + + return ret; +} diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index 174f1ccb0..7cc7e69d9 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -21,7 +21,7 @@ class cmGlobalVisualStudio11Generator: { public: cmGlobalVisualStudio11Generator(const char* name, - const char* architectureId, const char* additionalPlatformDefinition); + const char* platformName, const char* additionalPlatformDefinition); static cmGlobalGeneratorFactory* NewFactory(); virtual void WriteSLNHeader(std::ostream& fout); @@ -34,7 +34,9 @@ public: protected: virtual const char* GetIDEVersion() { return "11.0"; } bool UseFolderProperty(); + static std::set<std::string> GetInstalledWindowsCESDKs(); private: class Factory; + friend class Factory; }; #endif diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index d77b84d2c..c56dfff15 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -25,17 +25,17 @@ public: if(!strcmp(name, vs12Win32generatorName)) { return new cmGlobalVisualStudio12Generator( - vs12Win32generatorName, NULL, NULL); + name, NULL, NULL); } if(!strcmp(name, vs12Win64generatorName)) { return new cmGlobalVisualStudio12Generator( - vs12Win64generatorName, "x64", "CMAKE_FORCE_WIN64"); + name, "x64", "CMAKE_FORCE_WIN64"); } if(!strcmp(name, vs12ARMgeneratorName)) { return new cmGlobalVisualStudio12Generator( - vs12ARMgeneratorName, "ARM", NULL); + name, "ARM", NULL); } return 0; } @@ -64,9 +64,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory() //---------------------------------------------------------------------------- cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator( - const char* name, const char* architectureId, + const char* name, const char* platformName, const char* additionalPlatformDefinition) - : cmGlobalVisualStudio11Generator(name, architectureId, + : cmGlobalVisualStudio11Generator(name, platformName, additionalPlatformDefinition) { this->FindMakeProgramFile = "CMakeVS12FindMake.cmake"; @@ -100,12 +100,3 @@ cmLocalGenerator *cmGlobalVisualStudio12Generator::CreateLocalGenerator() lg->SetGlobalGenerator(this); return lg; } - -//---------------------------------------------------------------------------- -bool cmGlobalVisualStudio12Generator::UseFolderProperty() -{ - // Intentionally skip over the parent class implementation and call the - // grand-parent class's implementation. Folders are not supported by the - // Express editions in VS10 and earlier, but they are in VS12 Express. - return cmGlobalVisualStudio8Generator::UseFolderProperty(); -} diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index 5844ee01e..8c8aeb1fd 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -21,7 +21,7 @@ class cmGlobalVisualStudio12Generator: { public: cmGlobalVisualStudio12Generator(const char* name, - const char* architectureId, const char* additionalPlatformDefinition); + const char* platformName, const char* additionalPlatformDefinition); static cmGlobalGeneratorFactory* NewFactory(); virtual void WriteSLNHeader(std::ostream& fout); @@ -31,9 +31,13 @@ public: /** TODO: VS 12 user macro support. */ virtual std::string GetUserMacrosDirectory() { return ""; } + + //in Visual Studio 2013 they detached the MSBuild tools version + //from the .Net Framework version and instead made it have it's own + //version number + virtual const char* GetToolsVersion() { return "12.0"; } protected: virtual const char* GetIDEVersion() { return "12.0"; } - bool UseFolderProperty(); private: class Factory; }; diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index 9f3af71bb..b3fabdade 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/Source/cmGlobalVisualStudio6Generator.cxx @@ -80,12 +80,15 @@ void cmGlobalVisualStudio6Generator::GenerateConfigurations(cmMakefile* mf) std::string cmGlobalVisualStudio6Generator ::GenerateBuildCommand(const char* makeProgram, const char *projectName, + const char *projectDir, const char* additionalOptions, const char *targetName, const char* config, bool ignoreErrors, bool) { + // Visual studio 6 doesn't need project dir + (void) projectDir; // Ingoring errors is not implemented in visual studio 6 (void) ignoreErrors; diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h index 40149e911..6bd39ca9a 100644 --- a/Source/cmGlobalVisualStudio6Generator.h +++ b/Source/cmGlobalVisualStudio6Generator.h @@ -54,6 +54,7 @@ public: */ virtual std::string GenerateBuildCommand(const char* makeProgram, const char *projectName, + const char *projectDir, const char* additionalOptions, const char *targetName, const char* config, diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 2494f559c..51efc466c 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -16,7 +16,8 @@ #include "cmake.h" //---------------------------------------------------------------------------- -cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator() +cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator( + const char* platformName) : cmGlobalVisualStudio7Generator(platformName) { this->FindMakeProgramFile = "CMakeVS71FindMake.cmake"; this->ProjectConfigurationSectionName = "ProjectConfiguration"; @@ -281,20 +282,20 @@ void cmGlobalVisualStudio71Generator const std::set<std::string>& configsPartOfDefaultBuild, const char* platformMapping) { + const char* platformName = + platformMapping ? platformMapping : this->GetPlatformName(); std::string guid = this->GetGUID(name); for(std::vector<std::string>::iterator i = this->Configurations.begin(); i != this->Configurations.end(); ++i) { fout << "\t\t{" << guid << "}." << *i - << ".ActiveCfg = " << *i << "|" - << (platformMapping ? platformMapping : "Win32") << std::endl; + << ".ActiveCfg = " << *i << "|" << platformName << std::endl; std::set<std::string>::const_iterator ci = configsPartOfDefaultBuild.find(*i); if(!(ci == configsPartOfDefaultBuild.end())) { fout << "\t\t{" << guid << "}." << *i - << ".Build.0 = " << *i << "|" - << (platformMapping ? platformMapping : "Win32") << std::endl; + << ".Build.0 = " << *i << "|" << platformName << std::endl; } } } diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index 6d91f97fc..e136db7ea 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -23,7 +23,7 @@ class cmGlobalVisualStudio71Generator : public cmGlobalVisualStudio7Generator { public: - cmGlobalVisualStudio71Generator(); + cmGlobalVisualStudio71Generator(const char* platformName = NULL); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalVisualStudio71Generator>(); } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 63cbdb890..b47566561 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -17,9 +17,16 @@ #include "cmMakefile.h" #include "cmake.h" -cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator() +cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator( + const char* platformName) { this->FindMakeProgramFile = "CMakeVS7FindMake.cmake"; + + if (!platformName) + { + platformName = "Win32"; + } + this->PlatformName = platformName; } @@ -31,6 +38,16 @@ void cmGlobalVisualStudio7Generator mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1"); mf->AddDefinition("CMAKE_GENERATOR_FC", "ifort"); this->AddPlatformDefinitions(mf); + if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) + { + mf->AddCacheDefinition( + "CMAKE_CONFIGURATION_TYPES", + "Debug;Release;MinSizeRel;RelWithDebInfo", + "Semicolon separated list of supported configuration types, " + "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " + "anything else will be ignored.", + cmCacheManager::STRING); + } // Create list of configurations requested by user's cache, if any. this->cmGlobalGenerator::EnableLanguage(lang, mf, optional); @@ -56,10 +73,12 @@ void cmGlobalVisualStudio7Generator std::string cmGlobalVisualStudio7Generator ::GenerateBuildCommand(const char* makeProgram, - const char *projectName, + const char *projectName, const char *projectDir, const char* additionalOptions, const char *targetName, const char* config, bool ignoreErrors, bool) { + // Visual studio 7 doesn't need project dir + (void) projectDir; // Ingoring errors is not implemented in visual studio 6 (void) ignoreErrors; @@ -132,6 +151,13 @@ cmLocalGenerator *cmGlobalVisualStudio7Generator::CreateLocalGenerator() return lg; } +//---------------------------------------------------------------------------- +void cmGlobalVisualStudio7Generator::AddPlatformDefinitions(cmMakefile* mf) +{ + cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf); + mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName()); +} + void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf) { // process the configurations @@ -589,20 +615,20 @@ void cmGlobalVisualStudio7Generator const std::set<std::string>& configsPartOfDefaultBuild, const char* platformMapping) { + const char* platformName = + platformMapping ? platformMapping : this->GetPlatformName(); std::string guid = this->GetGUID(name); for(std::vector<std::string>::iterator i = this->Configurations.begin(); i != this->Configurations.end(); ++i) { fout << "\t\t{" << guid << "}." << *i - << ".ActiveCfg = " << *i << "|" - << (platformMapping ? platformMapping : "Win32") << "\n"; + << ".ActiveCfg = " << *i << "|" << platformName << "\n"; std::set<std::string>::const_iterator ci = configsPartOfDefaultBuild.find(*i); if(!(ci == configsPartOfDefaultBuild.end())) { fout << "\t\t{" << guid << "}." << *i - << ".Build.0 = " << *i << "|" - << (platformMapping ? platformMapping : "Win32") << "\n"; + << ".Build.0 = " << *i << "|" << platformName << "\n"; } } } diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 6e786201b..4d22cff88 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -26,7 +26,7 @@ struct cmIDEFlagTable; class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator { public: - cmGlobalVisualStudio7Generator(); + cmGlobalVisualStudio7Generator(const char* platformName = NULL); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalVisualStudio7Generator>(); } @@ -36,9 +36,14 @@ public: return cmGlobalVisualStudio7Generator::GetActualName();} static const char* GetActualName() {return "Visual Studio 7";} + ///! Get the name for the platform. + const char* GetPlatformName() const { return this->PlatformName.c_str(); } + ///! Create a local generator appropriate to this Global Generator virtual cmLocalGenerator *CreateLocalGenerator(); + virtual void AddPlatformDefinitions(cmMakefile* mf); + /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); @@ -55,6 +60,7 @@ public: */ virtual std::string GenerateBuildCommand(const char* makeProgram, const char *projectName, + const char *projectDir, const char* additionalOptions, const char *targetName, const char* config, @@ -152,6 +158,7 @@ protected: // Set during OutputSLNFile with the name of the current project. // There is one SLN file per project. std::string CurrentProject; + std::string PlatformName; }; #define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK" diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 864e8db02..e4244e062 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -57,8 +57,7 @@ public: } cmGlobalVisualStudio8Generator* ret = new cmGlobalVisualStudio8Generator( - name, parser.GetArchitectureFamily(), NULL); - ret->PlatformName = p; + name, p, NULL); ret->WindowsCEVersion = parser.GetOSVersion(); return ret; } @@ -96,16 +95,14 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio8Generator::NewFactory() //---------------------------------------------------------------------------- cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator( - const char* name, const char* architectureId, + const char* name, const char* platformName, const char* additionalPlatformDefinition) + : cmGlobalVisualStudio71Generator(platformName) { this->FindMakeProgramFile = "CMakeVS8FindMake.cmake"; this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms"; this->Name = name; - if (architectureId) - { - this->ArchitectureId = architectureId; - } + if (additionalPlatformDefinition) { this->AdditionalPlatformDefinition = additionalPlatformDefinition; @@ -113,20 +110,6 @@ cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator( } //---------------------------------------------------------------------------- -const char* cmGlobalVisualStudio8Generator::GetPlatformName() const -{ - if (!this->PlatformName.empty()) - { - return this->PlatformName.c_str(); - } - if (this->ArchitectureId == "X86") - { - return "Win32"; - } - return this->ArchitectureId.c_str(); -} - -//---------------------------------------------------------------------------- ///! Create a local generator appropriate to this Global Generator cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator() { @@ -142,7 +125,6 @@ cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator() void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf) { cmGlobalVisualStudio71Generator::AddPlatformDefinitions(mf); - mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName()); if(this->TargetsWindowsCE()) { diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index bcbd7a0bd..d18174275 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -24,14 +24,12 @@ class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator { public: cmGlobalVisualStudio8Generator(const char* name, - const char* architectureId, const char* additionalPlatformDefinition); + const char* platformName, const char* additionalPlatformDefinition); static cmGlobalGeneratorFactory* NewFactory(); ///! Get the name for the generator. virtual const char* GetName() const {return this->Name.c_str();} - const char* GetPlatformName() const; - /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); @@ -87,7 +85,6 @@ protected: const char* path, cmTarget &t); std::string Name; - std::string PlatformName; std::string WindowsCEVersion; private: diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index 2082384e6..fba6ed1ee 100644 --- a/Source/cmGlobalVisualStudio9Generator.cxx +++ b/Source/cmGlobalVisualStudio9Generator.cxx @@ -62,8 +62,7 @@ public: } cmGlobalVisualStudio9Generator* ret = new cmGlobalVisualStudio9Generator( - name, parser.GetArchitectureFamily(), NULL); - ret->PlatformName = p; + name, p, NULL); ret->WindowsCEVersion = parser.GetOSVersion(); return ret; } @@ -102,9 +101,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory() //---------------------------------------------------------------------------- cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator( - const char* name, const char* architectureId, + const char* name, const char* platformName, const char* additionalPlatformDefinition) - : cmGlobalVisualStudio8Generator(name, architectureId, + : cmGlobalVisualStudio8Generator(name, platformName, additionalPlatformDefinition) { this->FindMakeProgramFile = "CMakeVS9FindMake.cmake"; diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h index 1310a93ac..202aa8d12 100644 --- a/Source/cmGlobalVisualStudio9Generator.h +++ b/Source/cmGlobalVisualStudio9Generator.h @@ -25,7 +25,7 @@ class cmGlobalVisualStudio9Generator : { public: cmGlobalVisualStudio9Generator(const char* name, - const char* architectureId, const char* additionalPlatformDefinition); + const char* platformName, const char* additionalPlatformDefinition); static cmGlobalGeneratorFactory* NewFactory(); ///! create the correct local generator diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 808664d44..59310162c 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -21,7 +21,6 @@ //---------------------------------------------------------------------------- cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator() { - this->ArchitectureId = "X86"; this->AdditionalPlatformDefinition = NULL; } @@ -449,7 +448,7 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) } } - // Collext explicit util dependencies (add_dependencies). + // Collect explicit util dependencies (add_dependencies). std::set<cmTarget*> utilDepends; for(TargetDependSet::const_iterator di = depends.begin(); di != depends.end(); ++di) @@ -499,9 +498,6 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) //---------------------------------------------------------------------------- void cmGlobalVisualStudioGenerator::AddPlatformDefinitions(cmMakefile* mf) { - mf->AddDefinition("MSVC_C_ARCHITECTURE_ID", this->ArchitectureId.c_str()); - mf->AddDefinition("MSVC_CXX_ARCHITECTURE_ID", this->ArchitectureId.c_str()); - if(this->AdditionalPlatformDefinition) { mf->AddDefinition(this->AdditionalPlatformDefinition, "TRUE"); diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 9d811706b..b665158c6 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -104,7 +104,6 @@ protected: std::string GetUtilityDepend(cmTarget* target); typedef std::map<cmTarget*, cmStdString> UtilityDependsMap; UtilityDependsMap UtilityDepends; - std::string ArchitectureId; const char* AdditionalPlatformDefinition; private: diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 3092abf95..c181c5926 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -260,6 +260,7 @@ void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const& std::string cmGlobalXCodeGenerator ::GenerateBuildCommand(const char* makeProgram, const char *projectName, + const char *projectDir, const char* additionalOptions, const char *targetName, const char* config, @@ -268,6 +269,7 @@ std::string cmGlobalXCodeGenerator { // Config is not used yet (void) ignoreErrors; + (void) projectDir; // now build the test if(makeProgram == 0 || !strlen(makeProgram)) @@ -429,13 +431,16 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, // Add XCODE depend helper std::string dir = mf->GetCurrentOutputDirectory(); - cmCustomCommandLine makecommand; - makecommand.push_back("make"); - makecommand.push_back("-C"); - makecommand.push_back(dir.c_str()); - makecommand.push_back("-f"); - makecommand.push_back(this->CurrentXCodeHackMakefile.c_str()); - makecommand.push_back(""); // placeholder, see below + cmCustomCommandLine makeHelper; + if(this->XcodeVersion < 50) + { + makeHelper.push_back("make"); + makeHelper.push_back("-C"); + makeHelper.push_back(dir.c_str()); + makeHelper.push_back("-f"); + makeHelper.push_back(this->CurrentXCodeHackMakefile.c_str()); + makeHelper.push_back(""); // placeholder, see below + } // Add ZERO_CHECK bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION"); @@ -475,17 +480,18 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, // run the depend check makefile as a post build rule // this will make sure that when the next target is built // things are up-to-date - if((target.GetType() == cmTarget::EXECUTABLE || + if(!makeHelper.empty() && + (target.GetType() == cmTarget::EXECUTABLE || // Nope - no post-build for OBJECT_LIRBRARY // target.GetType() == cmTarget::OBJECT_LIBRARY || target.GetType() == cmTarget::STATIC_LIBRARY || target.GetType() == cmTarget::SHARED_LIBRARY || target.GetType() == cmTarget::MODULE_LIBRARY)) { - makecommand[makecommand.size()-1] = + makeHelper[makeHelper.size()-1] = // fill placeholder this->PostBuildMakeTarget(target.GetName(), "$(CONFIGURATION)"); cmCustomCommandLines commandLines; - commandLines.push_back(makecommand); + commandLines.push_back(makeHelper); lg->GetMakefile()->AddCustomCommandToTarget(target.GetName(), no_depends, commandLines, @@ -679,10 +685,6 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, { // Add flags from target and source file properties. std::string flags; - if(cmtarget.GetProperty("COMPILE_FLAGS")) - { - lg->AppendFlags(flags, cmtarget.GetProperty("COMPILE_FLAGS")); - } const char* srcfmt = sf->GetProperty("Fortran_FORMAT"); switch(this->CurrentLocalGenerator->GetFortranFormat(srcfmt)) { @@ -746,12 +748,6 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, } } - if(cmtarget.IsCFBundleOnApple()) - { - cmtarget.SetProperty("PREFIX", ""); - cmtarget.SetProperty("SUFFIX", ""); - } - // Add the fileRef to the top level Resources group/folder if it is not // already there. // @@ -839,7 +835,7 @@ GetSourcecodeValueFromFileExtension(const std::string& _ext, // // Already specialized above or we leave sourcecode == "sourcecode" // // which is probably the most correct choice. Extensionless headers, // // for example... Or file types unknown to Xcode that do not map to a - // // valid lastKnownFileType value. + // // valid explicitFileType value. // } return sourcecode; @@ -881,8 +877,10 @@ cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( } std::string sourcecode = GetSourcecodeValueFromFileExtension(ext, lang); - - fileRef->AddAttribute("lastKnownFileType", + const char* attribute = (sourcecode == "file.storyboard") ? + "lastKnownFileType" : + "explicitFileType"; + fileRef->AddAttribute(attribute, this->CreateString(sourcecode.c_str())); // Store the file path relative to the top of the source tree. @@ -1003,7 +1001,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, *i, cmtarget); cmXCodeObject* fr = xsf->GetObject("fileRef"); cmXCodeObject* filetype = - fr->GetObject()->GetObject("lastKnownFileType"); + fr->GetObject()->GetObject("explicitFileType"); cmTarget::SourceFileFlags tsFlags = cmtarget.GetTargetSourceFileFlags(*i); @@ -1035,18 +1033,21 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, } } - // Add object library contents as external objects. (Equivalent to - // the externalObjFiles above, except each one is not a cmSourceFile - // within the target.) - std::vector<std::string> objs; - this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs); - for(std::vector<std::string>::const_iterator - oi = objs.begin(); oi != objs.end(); ++oi) + if(this->XcodeVersion < 50) { - std::string obj = *oi; - cmXCodeObject* xsf = - this->CreateXCodeSourceFileFromPath(obj, cmtarget, ""); - externalObjFiles.push_back(xsf); + // Add object library contents as external objects. (Equivalent to + // the externalObjFiles above, except each one is not a cmSourceFile + // within the target.) + std::vector<std::string> objs; + this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs); + for(std::vector<std::string>::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string obj = *oi; + cmXCodeObject* xsf = + this->CreateXCodeSourceFileFromPath(obj, cmtarget, ""); + externalObjFiles.push_back(xsf); + } } // some build phases only apply to bundles and/or frameworks @@ -1319,8 +1320,40 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, = cmtarget.GetPreBuildCommands(); std::vector<cmCustomCommand> const & prelink = cmtarget.GetPreLinkCommands(); - std::vector<cmCustomCommand> const & postbuild + std::vector<cmCustomCommand> postbuild = cmtarget.GetPostBuildCommands(); + + if(cmtarget.GetType() == cmTarget::SHARED_LIBRARY && + !cmtarget.IsFrameworkOnApple()) + { + cmCustomCommandLines cmd; + cmd.resize(1); + cmd[0].push_back(this->CurrentMakefile->GetDefinition("CMAKE_COMMAND")); + cmd[0].push_back("-E"); + cmd[0].push_back("cmake_symlink_library"); + std::string str_file = "$<TARGET_FILE:"; + str_file += cmtarget.GetName(); + str_file += ">"; + std::string str_so_file = "$<TARGET_SONAME_FILE:"; + str_so_file += cmtarget.GetName(); + str_so_file += ">"; + std::string str_link_file = "$<TARGET_LINKER_FILE:"; + str_link_file += cmtarget.GetName(); + str_link_file += ">"; + cmd[0].push_back(str_file); + cmd[0].push_back(str_so_file); + cmd[0].push_back(str_link_file); + + cmCustomCommand command(this->CurrentMakefile, + std::vector<std::string>(), + std::vector<std::string>(), + cmd, + "Creating symlinks", + ""); + + postbuild.push_back(command); + } + std::vector<cmSourceFile*>const &classes = cmtarget.GetSourceFiles(); // add all the sources std::vector<cmCustomCommand> commands; @@ -1674,6 +1707,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, this->CurrentLocalGenerator->AddLanguageFlags(cflags, "C", configName); this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target, "C", configName); + this->CurrentLocalGenerator-> + AddCompileOptions(cflags, &target, "C", configName); } // Add language-specific flags. @@ -1682,11 +1717,17 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, // Add shared-library flags if needed. this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target, lang, configName); + + this->CurrentLocalGenerator->AddVisibilityPresetFlags(flags, &target, + lang); + + this->CurrentLocalGenerator-> + AddCompileOptions(flags, &target, lang, configName); } else if(binary) { cmSystemTools::Error - ("CMake can not determine linker language for target:", + ("CMake can not determine linker language for target: ", target.GetName()); return; } @@ -1709,58 +1750,59 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, this->AppendDefines(ppDefs, exportMacro); } cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target); - this->AppendDefines(ppDefs, - target.GetCompileDefinitions(configName).c_str()); + std::vector<std::string> targetDefines; + target.GetCompileDefinitions(targetDefines, configName); + this->AppendDefines(ppDefs, targetDefines); buildSettings->AddAttribute ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList()); + std::string extraLinkOptionsVar; std::string extraLinkOptions; if(target.GetType() == cmTarget::EXECUTABLE) { - extraLinkOptions = - this->CurrentMakefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS"); - std::string var = "CMAKE_EXE_LINKER_FLAGS_"; - var += cmSystemTools::UpperCase(configName); - std::string val = - this->CurrentMakefile->GetSafeDefinition(var.c_str()); - if(val.size()) - { - extraLinkOptions += " "; - extraLinkOptions += val; - } + extraLinkOptionsVar = "CMAKE_EXE_LINKER_FLAGS"; } - if(target.GetType() == cmTarget::SHARED_LIBRARY) + else if(target.GetType() == cmTarget::SHARED_LIBRARY) + { + extraLinkOptionsVar = "CMAKE_SHARED_LINKER_FLAGS"; + } + else if(target.GetType() == cmTarget::MODULE_LIBRARY) { - extraLinkOptions = this->CurrentMakefile-> - GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS"); + extraLinkOptionsVar = "CMAKE_MODULE_LINKER_FLAGS"; } - if(target.GetType() == cmTarget::MODULE_LIBRARY) + if(extraLinkOptionsVar.size()) { - extraLinkOptions = this->CurrentMakefile-> - GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS"); + this->CurrentLocalGenerator + ->AddConfigVariableFlags(extraLinkOptions, + extraLinkOptionsVar.c_str(), + configName); } - const char* linkFlagsProp = "LINK_FLAGS"; if(target.GetType() == cmTarget::OBJECT_LIBRARY || target.GetType() == cmTarget::STATIC_LIBRARY) { - linkFlagsProp = "STATIC_LIBRARY_FLAGS"; + this->CurrentLocalGenerator + ->GetStaticLibraryFlags(extraLinkOptions, + cmSystemTools::UpperCase(configName), + &target); } - const char* targetLinkFlags = target.GetProperty(linkFlagsProp); - if(targetLinkFlags) - { - extraLinkOptions += " "; - extraLinkOptions += targetLinkFlags; - } - if(configName && *configName) + else { - std::string linkFlagsVar = linkFlagsProp; - linkFlagsVar += "_"; - linkFlagsVar += cmSystemTools::UpperCase(configName); - if(const char* linkFlags = target.GetProperty(linkFlagsVar.c_str())) + const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"); + if(targetLinkFlags) { - extraLinkOptions += " "; - extraLinkOptions += linkFlags; + this->CurrentLocalGenerator-> + AppendFlags(extraLinkOptions, targetLinkFlags); + } + if(configName && *configName) + { + std::string linkFlagsVar = "LINK_FLAGS_"; + linkFlagsVar += cmSystemTools::UpperCase(configName); + if(const char* linkFlags = target.GetProperty(linkFlagsVar.c_str())) + { + this->CurrentLocalGenerator-> + AppendFlags(extraLinkOptions, linkFlags); + } } } @@ -1797,9 +1839,34 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, std::string pnprefix; std::string pnbase; std::string pnsuffix; - target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName); + const char* version = target.GetProperty("VERSION"); + const char* soversion = target.GetProperty("SOVERSION"); + if(!target.HasSOName(configName) || target.IsFrameworkOnApple()) + { + version = 0; + soversion = 0; + } + if(version && !soversion) + { + soversion = version; + } + if(!version && soversion) + { + version = soversion; + } + + std::string realName = pnbase; + std::string soName = pnbase; + if(version && soversion) + { + realName += "."; + realName += version; + soName += "."; + soName += soversion; + } + // Set attributes to specify the proper name for the target. std::string pndir = this->CurrentMakefile->GetCurrentOutputDirectory(); if(target.GetType() == cmTarget::STATIC_LIBRARY || @@ -1823,6 +1890,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, pndir = target.GetDirectory(configName); } + if(target.IsFrameworkOnApple() || target.IsCFBundleOnApple()) + { + pnprefix = ""; + } + buildSettings->AddAttribute("EXECUTABLE_PREFIX", this->CreateString(pnprefix.c_str())); buildSettings->AddAttribute("EXECUTABLE_SUFFIX", @@ -1852,7 +1924,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, // Store the product name for all target types. buildSettings->AddAttribute("PRODUCT_NAME", - this->CreateString(pnbase.c_str())); + this->CreateString(realName.c_str())); buildSettings->AddAttribute("SYMROOT", this->CreateString(pndir.c_str())); @@ -1930,9 +2002,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, { if(target.GetPropertyAsBool("FRAMEWORK")) { - std::string version = target.GetFrameworkVersion(); + std::string fw_version = target.GetFrameworkVersion(); buildSettings->AddAttribute("FRAMEWORK_VERSION", - this->CreateString(version.c_str())); + this->CreateString(fw_version.c_str())); std::string plist = this->ComputeInfoPListLocation(target); // Xcode will create the final version of Info.plist at build time, @@ -2152,25 +2224,55 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, if(target.GetType() == cmTarget::SHARED_LIBRARY) { // Get the install_name directory for the build tree. - install_name_dir = target.GetInstallNameDirForBuildTree(configName, true); - if(install_name_dir.empty()) - { - // Xcode will not pass the -install_name option at all if INSTALL_PATH - // is not given or is empty. We must explicitly put the flag in the - // link flags to create an install_name with just the library soname. - extraLinkOptions += " -install_name "; - extraLinkOptions += target.GetFullName(configName); - } - else + install_name_dir = target.GetInstallNameDirForBuildTree(configName); + // Xcode doesn't create the correct install_name in some cases. + // That is, if the INSTALL_PATH is empty, or if we have versioning + // of dylib libraries, we want to specify the install_name. + // This is done by adding a link flag to create an install_name + // with just the library soname. + std::string install_name; + if(!install_name_dir.empty()) { // Convert to a path for the native build tool. cmSystemTools::ConvertToUnixSlashes(install_name_dir); - // do not escape spaces on this since it is only a single path + install_name += install_name_dir; + install_name += "/"; + } + install_name += target.GetSOName(configName); + + if((realName != soName) || install_name_dir.empty()) + { + install_name_dir = ""; + extraLinkOptions += " -install_name "; + extraLinkOptions += XCodeEscapePath(install_name.c_str()); } } buildSettings->AddAttribute("INSTALL_PATH", this->CreateString(install_name_dir.c_str())); + // Create the LD_RUNPATH_SEARCH_PATHS + cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + if(pcli) + { + std::string search_paths; + std::vector<std::string> runtimeDirs; + pcli->GetRPath(runtimeDirs, false); + for(std::vector<std::string>::const_iterator i = runtimeDirs.begin(); + i != runtimeDirs.end(); ++i) + { + if(!search_paths.empty()) + { + search_paths += " "; + } + search_paths += this->XCodeEscapePath((*i).c_str()); + } + if(!search_paths.empty()) + { + buildSettings->AddAttribute("LD_RUNPATH_SEARCH_PATHS", + this->CreateString(search_paths.c_str())); + } + } + buildSettings->AddAttribute("OTHER_LDFLAGS", this->CreateString(extraLinkOptions.c_str())); buildSettings->AddAttribute("OTHER_REZFLAGS", @@ -2235,8 +2337,39 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, { if(i->first.find("XCODE_ATTRIBUTE_") == 0) { - buildSettings->AddAttribute(i->first.substr(16).c_str(), - this->CreateString(i->second.GetValue())); + cmStdString attribute = i->first.substr(16); + // Handle [variant=<config>] condition explicitly here. + cmStdString::size_type beginVariant = + attribute.find("[variant="); + if (beginVariant != cmStdString::npos) + { + cmStdString::size_type endVariant = + attribute.find("]", beginVariant+9); + if (endVariant != cmStdString::npos) + { + // Compare the variant to the configuration. + cmStdString variant = + attribute.substr(beginVariant+9, endVariant-beginVariant-9); + if (variant == configName) + { + // The variant matches the configuration so use this + // attribute but drop the [variant=<config>] condition. + attribute.erase(beginVariant, endVariant-beginVariant+1); + } + else + { + // The variant does not match the configuration so + // do not use this attribute. + attribute.clear(); + } + } + } + + if (!attribute.empty()) + { + buildSettings->AddAttribute(attribute.c_str(), + this->CreateString(i->second.GetValue())); + } } } } @@ -2641,13 +2774,6 @@ void cmGlobalXCodeGenerator } } - // Skip link information for static libraries. - if(cmtarget->GetType() == cmTarget::OBJECT_LIBRARY || - cmtarget->GetType() == cmTarget::STATIC_LIBRARY) - { - return; - } - // Loop over configuration types and set per-configuration info. for(std::vector<std::string>::iterator i = this->CurrentConfigurationTypes.begin(); @@ -2660,6 +2786,31 @@ void cmGlobalXCodeGenerator configName = 0; } + if(this->XcodeVersion >= 50) + { + // Add object library contents as link flags. + std::string linkObjs; + const char* sep = ""; + std::vector<std::string> objs; + this->GetGeneratorTarget(cmtarget)->UseObjectLibraries(objs); + for(std::vector<std::string>::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + linkObjs += sep; + sep = " "; + linkObjs += this->XCodeEscapePath(oi->c_str()); + } + this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS", + linkObjs.c_str(), configName); + } + + // Skip link information for object libraries. + if(cmtarget->GetType() == cmTarget::OBJECT_LIBRARY || + cmtarget->GetType() == cmTarget::STATIC_LIBRARY) + { + continue; + } + // Compute the link library and directory information. cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName); if(!pcli) @@ -3214,8 +3365,11 @@ void cmGlobalXCodeGenerator cmXCodeObject* t = *i; this->AddDependAndLinkInformation(t); } - // now create xcode depend hack makefile - this->CreateXCodeDependHackTarget(targets); + if(this->XcodeVersion < 50) + { + // now create xcode depend hack makefile + this->CreateXCodeDependHackTarget(targets); + } // now add all targets to the root object cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST); for(std::vector<cmXCodeObject*>::iterator i = targets.begin(); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 131a6e6d5..c05394346 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -55,6 +55,7 @@ public: */ virtual std::string GenerateBuildCommand(const char* makeProgram, const char *projectName, + const char *projectDir, const char* additionalOptions, const char *targetName, const char* config, @@ -84,6 +85,7 @@ public: virtual bool IsMultiConfig(); virtual bool SetGeneratorToolset(std::string const& ts); + void AppendFlag(std::string& flags, std::string const& flag); private: cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget, cmSourceGroup* sg); @@ -197,7 +199,6 @@ private: void AppendDefines(BuildObjectListOrString& defs, std::vector<std::string> const& defines, bool dflag = false); - void AppendFlag(std::string& flags, std::string const& flag); protected: virtual const char* GetInstallTargetName() const { return "install"; } diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index 76a60cfcd..34a9c7c78 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -165,6 +165,11 @@ void cmIDEOptions::AddDefines(const char* defines) cmSystemTools::ExpandListArgument(defines, this->Defines); } } +//---------------------------------------------------------------------------- +void cmIDEOptions::AddDefines(const std::vector<std::string> &defines) +{ + this->Defines.insert(this->Defines.end(), defines.begin(), defines.end()); +} //---------------------------------------------------------------------------- void cmIDEOptions::AddFlag(const char* flag, const char* value) diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h index e556bdeca..e78af3ee4 100644 --- a/Source/cmIDEOptions.h +++ b/Source/cmIDEOptions.h @@ -27,6 +27,7 @@ public: // Store definitions and flags. void AddDefine(const std::string& define); void AddDefines(const char* defines); + void AddDefines(const std::vector<std::string> &defines); void AddFlag(const char* flag, const char* value); void RemoveFlag(const char* flag); const char* GetFlag(const char* flag); diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 56d717031..57cec5bbb 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -406,38 +406,6 @@ namespace } //========================================================================= - enum Op { OpLess, OpEqual, OpGreater }; - bool HandleVersionCompare(Op op, const char* lhs_str, const char* rhs_str) - { - // Parse out up to 8 components. - unsigned int lhs[8] = {0,0,0,0,0,0,0,0}; - unsigned int rhs[8] = {0,0,0,0,0,0,0,0}; - sscanf(lhs_str, "%u.%u.%u.%u.%u.%u.%u.%u", - &lhs[0], &lhs[1], &lhs[2], &lhs[3], - &lhs[4], &lhs[5], &lhs[6], &lhs[7]); - sscanf(rhs_str, "%u.%u.%u.%u.%u.%u.%u.%u", - &rhs[0], &rhs[1], &rhs[2], &rhs[3], - &rhs[4], &rhs[5], &rhs[6], &rhs[7]); - - // Do component-wise comparison. - for(unsigned int i=0; i < 8; ++i) - { - if(lhs[i] < rhs[i]) - { - // lhs < rhs, so true if operation is LESS - return op == OpLess; - } - else if(lhs[i] > rhs[i]) - { - // lhs > rhs, so true if operation is GREATER - return op == OpGreater; - } - } - // lhs == rhs, so true if operation is EQUAL - return op == OpEqual; - } - - //========================================================================= // level 0 processes parenthetical expressions bool HandleLevel0(std::list<std::string> &newArgs, cmMakefile *makefile, @@ -723,16 +691,16 @@ namespace { def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile); def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile); - Op op = OpEqual; + cmSystemTools::CompareOp op = cmSystemTools::OP_EQUAL; if(*argP1 == "VERSION_LESS") { - op = OpLess; + op = cmSystemTools::OP_LESS; } else if(*argP1 == "VERSION_GREATER") { - op = OpGreater; + op = cmSystemTools::OP_GREATER; } - bool result = HandleVersionCompare(op, def, def2); + bool result = cmSystemTools::VersionCompare(op, def, def2); HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); } diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx index 0d5f67b78..bb891d6fc 100644 --- a/Source/cmIncludeCommand.cxx +++ b/Source/cmIncludeCommand.cxx @@ -61,7 +61,7 @@ bool cmIncludeCommand noPolicyScope = true; } else if(i > 1) // compat.: in previous cmake versions the second - // parameter was ignore if it wasn't "OPTIONAL" + // parameter was ignored if it wasn't "OPTIONAL" { std::string errorText = "called with invalid argument: "; errorText += args[i]; diff --git a/Source/cmIncludeCommand.h b/Source/cmIncludeCommand.h index c46c02d71..d97b7c3f5 100644 --- a/Source/cmIncludeCommand.h +++ b/Source/cmIncludeCommand.h @@ -55,7 +55,7 @@ public: */ virtual const char* GetTerseDocumentation() const { - return "Read CMake listfile code from the given file."; + return "Load and run CMake code from a file or module."; } /** @@ -66,9 +66,10 @@ public: return " include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>]\n" " [NO_POLICY_SCOPE])\n" - "Reads CMake listfile code from the given file. Commands in the file " - "are processed immediately as if they were written in place of the " - "include command. If OPTIONAL is present, then no error " + "Load and run CMake code from the file given. " + "Variable reads and writes access the scope of the caller " + "(dynamic scoping). " + "If OPTIONAL is present, then no error " "is raised if the file does not exist. If RESULT_VARIABLE is given " "the variable will be set to the full filename which " "has been included or NOTFOUND if it failed.\n" diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index dcd418b45..3c76bd638 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -219,6 +219,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) cmCAStringVector runtimeArgVector (&argHelper,"RUNTIME",&group); cmCAStringVector frameworkArgVector (&argHelper,"FRAMEWORK",&group); cmCAStringVector bundleArgVector (&argHelper,"BUNDLE",&group); + cmCAStringVector includesArgVector (&argHelper,"INCLUDES",&group); cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER",&group); cmCAStringVector publicHeaderArgVector (&argHelper,"PUBLIC_HEADER",&group); cmCAStringVector resourceArgVector (&argHelper,"RESOURCE",&group); @@ -247,6 +248,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName); cmInstallCommandArguments publicHeaderArgs(this->DefaultComponentName); cmInstallCommandArguments resourceArgs(this->DefaultComponentName); + cmInstallCommandIncludesArgument includesArgs; // now parse the args for specific parts of the target (e.g. LIBRARY, // RUNTIME, ARCHIVE etc. @@ -258,6 +260,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs); publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs); resourceArgs.Parse (&resourceArgVector.GetVector(), &unknownArgs); + includesArgs.Parse (&includesArgVector.GetVector(), &unknownArgs); if(!unknownArgs.empty()) { @@ -359,6 +362,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) targetIt!=targetList.GetVector().end(); ++targetIt) { + + if (this->Makefile->IsAlias(targetIt->c_str())) + { + cmOStringStream e; + e << "TARGETS given target \"" << (*targetIt) + << "\" which is an alias."; + this->SetError(e.str().c_str()); + return false; + } // Lookup this target in the current directory. if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str())) { @@ -747,6 +759,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) te->RuntimeGenerator = runtimeGenerator; this->Makefile->GetLocalGenerator()->GetGlobalGenerator() ->GetExportSets()[exports.GetString()]->AddTargetExport(te); + + std::vector<std::string> dirs = includesArgs.GetIncludeDirs(); + if(!dirs.empty()) + { + std::string dirString; + const char *sep = ""; + for (std::vector<std::string>::const_iterator it = dirs.begin(); + it != dirs.end(); ++it) + { + te->InterfaceIncludeDirectories += sep; + te->InterfaceIncludeDirectories += *it; + sep = ";"; + } + } } } @@ -1196,6 +1222,8 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) cmInstallCommandArguments ica(this->DefaultComponentName); cmCAString exp(&ica.Parser, "EXPORT"); cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup); + cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES", + &ica.ArgumentGroup); cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup); exp.Follows(0); @@ -1268,15 +1296,40 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) } } + cmExportSet *exportSet = this->Makefile->GetLocalGenerator() + ->GetGlobalGenerator()->GetExportSets()[exp.GetString()]; + if (exportOld.IsEnabled()) + { + for(std::vector<cmTargetExport*>::const_iterator + tei = exportSet->GetTargetExports()->begin(); + tei != exportSet->GetTargetExports()->end(); ++tei) + { + cmTargetExport const* te = *tei; + const bool newCMP0022Behavior = + te->Target->GetPolicyStatusCMP0022() != cmPolicies::WARN + && te->Target->GetPolicyStatusCMP0022() != cmPolicies::OLD; + + if(!newCMP0022Behavior) + { + cmOStringStream e; + e << "INSTALL(EXPORT) given keyword \"" + << "EXPORT_LINK_INTERFACE_LIBRARIES" << "\", but target \"" + << te->Target->GetName() + << "\" does not have policy CMP0022 set to NEW."; + this->SetError(e.str().c_str()); + return false; + } + } + } + // Create the export install generator. cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator( - this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->GetExportSets()[exp.GetString()], + exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(), ica.GetConfigurations(), ica.GetComponent().c_str(), fname.c_str(), - name_space.GetCString(), this->Makefile); + name_space.GetCString(), exportOld.IsEnabled(), this->Makefile); this->Makefile->AddInstallGenerator(exportGenerator); return true; diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 7c060090d..65095011f 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -102,6 +102,7 @@ public: " [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE|\n" " PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]\n" " [DESTINATION <dir>]\n" + " [INCLUDES DESTINATION [<dir> ...]]\n" " [PERMISSIONS permissions...]\n" " [CONFIGURATIONS [Debug|Release|...]]\n" " [COMPONENT <component>]\n" @@ -130,6 +131,10 @@ public: "all target types. If only one is given then only targets of that " "type will be installed (which can be used to install just a DLL or " "just an import library)." + "The INCLUDES DESTINATION specifies a list of directories which will " + "be added to the INTERFACE_INCLUDE_DIRECTORIES of the <targets> when " + "exported by install(EXPORT). If a relative path is specified, it is " + "treated as relative to the $<INSTALL_PREFIX>." "\n" "The PRIVATE_HEADER, PUBLIC_HEADER, and RESOURCE arguments cause " "subsequent properties to be applied to installing a FRAMEWORK " @@ -291,6 +296,7 @@ public: " [NAMESPACE <namespace>] [FILE <name>.cmake]\n" " [PERMISSIONS permissions...]\n" " [CONFIGURATIONS [Debug|Release|...]]\n" + " [EXPORT_LINK_INTERFACE_LIBRARIES]\n" " [COMPONENT <component>])\n" "The EXPORT form generates and installs a CMake file containing code " "to import targets from the installation tree into another project. " @@ -306,6 +312,10 @@ public: "installed when one of the named configurations is installed. " "Additionally, the generated import file will reference only the " "matching target configurations. " + "The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if present, causes the " + "contents of the properties matching " + "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? to be exported, when " + "policy CMP0022 is NEW. " "If a COMPONENT option is specified that does not match that given " "to the targets associated with <export-name> the behavior is " "undefined. " diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx index 8e48f08e6..91ea861a4 100644 --- a/Source/cmInstallCommandArguments.cxx +++ b/Source/cmInstallCommandArguments.cxx @@ -203,3 +203,37 @@ bool cmInstallCommandArguments::CheckPermissions( // This is not a valid permission. return false; } + +cmInstallCommandIncludesArgument::cmInstallCommandIncludesArgument() +{ + +} + +const std::vector<std::string>& +cmInstallCommandIncludesArgument::GetIncludeDirs() const +{ + return this->IncludeDirs; +} + +void cmInstallCommandIncludesArgument::Parse( + const std::vector<std::string>* args, + std::vector<std::string>*) +{ + if(args->empty()) + { + return; + } + std::vector<std::string>::const_iterator it = args->begin(); + ++it; + for ( ; it != args->end(); ++it) + { + std::string dir = *it; + if (!cmSystemTools::FileIsFullPath(it->c_str()) + && cmGeneratorExpression::Find(*it) == std::string::npos) + { + dir = "$<INSTALL_PREFIX>/" + dir; + } + cmSystemTools::ConvertToUnixSlashes(dir); + this->IncludeDirs.push_back(dir); + } +} diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h index 01f7d5679..90347e668 100644 --- a/Source/cmInstallCommandArguments.h +++ b/Source/cmInstallCommandArguments.h @@ -65,4 +65,17 @@ class cmInstallCommandArguments bool CheckPermissions(); }; +class cmInstallCommandIncludesArgument +{ + public: + cmInstallCommandIncludesArgument(); + void Parse(const std::vector<std::string>* args, + std::vector<std::string>* unconsumedArgs); + + const std::vector<std::string>& GetIncludeDirs() const; + + private: + std::vector<std::string> IncludeDirs; +}; + #endif diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 0a645a8fa..3e9e6ac02 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -33,12 +33,14 @@ cmInstallExportGenerator::cmInstallExportGenerator( std::vector<std::string> const& configurations, const char* component, const char* filename, const char* name_space, + bool exportOld, cmMakefile* mf) :cmInstallGenerator(destination, configurations, component) ,ExportSet(exportSet) ,FilePermissions(file_permissions) ,FileName(filename) ,Namespace(name_space) + ,ExportOld(exportOld) ,Makefile(mf) { this->EFGen = new cmExportInstallFileGenerator(this); @@ -137,6 +139,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os) // Generate the import file for this export set. this->EFGen->SetExportFile(this->MainImportFile.c_str()); this->EFGen->SetNamespace(this->Namespace.c_str()); + this->EFGen->SetExportOld(this->ExportOld); if(this->ConfigurationTypes->empty()) { if(this->ConfigurationName && *this->ConfigurationName) diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index 7aff7314c..37b55932f 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -31,7 +31,7 @@ public: const std::vector<std::string>& configurations, const char* component, const char* filename, const char* name_space, - cmMakefile* mf); + bool exportOld, cmMakefile* mf); ~cmInstallExportGenerator(); cmExportSet* GetExportSet() {return this->ExportSet;} @@ -52,6 +52,7 @@ protected: std::string FilePermissions; std::string FileName; std::string Namespace; + bool ExportOld; cmMakefile* Makefile; std::string TempDir; diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 5f9b6585e..c9624c8e0 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -198,14 +198,12 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, // Install the whole framework directory. type = cmInstallType_DIRECTORY; literal_args += " USE_SOURCE_PERMISSIONS"; - std::string from1 = fromDirConfig + targetName + ".framework"; + + std::string from1 = fromDirConfig + targetName; + from1 = cmSystemTools::GetFilenamePath(from1); // Tweaks apply to the binary inside the bundle. - std::string to1 = toDir + targetName; - to1 += ".framework/Versions/"; - to1 += this->Target->GetFrameworkVersion(); - to1 += "/"; - to1 += targetName; + std::string to1 = toDir + targetNameReal; filesFrom.push_back(from1); filesTo.push_back(to1); @@ -528,7 +526,7 @@ cmInstallTargetGenerator // components of the install_name field then we need to create a // mapping to be applied after installation. std::string for_build = tgt->GetInstallNameDirForBuildTree(config); - std::string for_install = tgt->GetInstallNameDirForInstallTree(config); + std::string for_install = tgt->GetInstallNameDirForInstallTree(); if(for_build != for_install) { // The directory portions differ. Append the filename to @@ -555,7 +553,7 @@ cmInstallTargetGenerator std::string for_build = this->Target->GetInstallNameDirForBuildTree(config); std::string for_install = - this->Target->GetInstallNameDirForInstallTree(config); + this->Target->GetInstallNameDirForInstallTree(); if(this->Target->IsFrameworkOnApple() && for_install.empty()) { @@ -608,6 +606,12 @@ cmInstallTargetGenerator return; } + // Skip if on Apple + if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + return; + } + // Get the link information for this target. // It can provide the RPATH. cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); @@ -647,30 +651,62 @@ cmInstallTargetGenerator return; } - // Construct the original rpath string to be replaced. - std::string oldRpath = cli->GetRPathString(false); - - // Get the install RPATH from the link information. - std::string newRpath = cli->GetChrpathString(); - - // Skip the rule if the paths are identical - if(oldRpath == newRpath) + if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { - return; - } + // If using install_name_tool, set up the rules to modify the rpaths. + std::string installNameTool = + this->Target->GetMakefile()-> + GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL"); + + std::vector<std::string> oldRuntimeDirs, newRuntimeDirs; + cli->GetRPath(oldRuntimeDirs, false); + cli->GetRPath(newRuntimeDirs, true); + + // Note: These are separate commands to avoid install_name_tool + // corruption on 10.6. + for(std::vector<std::string>::const_iterator i = oldRuntimeDirs.begin(); + i != oldRuntimeDirs.end(); ++i) + { + os << indent << "execute_process(COMMAND " << installNameTool << "\n"; + os << indent << " -delete_rpath \"" << *i << "\"\n"; + os << indent << " \"" << toDestDirPath << "\")\n"; + } - // Write a rule to run chrpath to set the install-tree RPATH - if(newRpath.empty()) - { - os << indent << "FILE(RPATH_REMOVE\n" - << indent << " FILE \"" << toDestDirPath << "\")\n"; + for(std::vector<std::string>::const_iterator i = newRuntimeDirs.begin(); + i != newRuntimeDirs.end(); ++i) + { + os << indent << "execute_process(COMMAND " << installNameTool << "\n"; + os << indent << " -add_rpath \"" << *i << "\"\n"; + os << indent << " \"" << toDestDirPath << "\")\n"; + } } else { - os << indent << "FILE(RPATH_CHANGE\n" - << indent << " FILE \"" << toDestDirPath << "\"\n" - << indent << " OLD_RPATH \"" << oldRpath << "\"\n" - << indent << " NEW_RPATH \"" << newRpath << "\")\n"; + // Construct the original rpath string to be replaced. + std::string oldRpath = cli->GetRPathString(false); + + // Get the install RPATH from the link information. + std::string newRpath = cli->GetChrpathString(); + + // Skip the rule if the paths are identical + if(oldRpath == newRpath) + { + return; + } + + // Write a rule to run chrpath to set the install-tree RPATH + if(newRpath.empty()) + { + os << indent << "FILE(RPATH_REMOVE\n" + << indent << " FILE \"" << toDestDirPath << "\")\n"; + } + else + { + os << indent << "FILE(RPATH_CHANGE\n" + << indent << " FILE \"" << toDestDirPath << "\"\n" + << indent << " OLD_RPATH \"" << oldRpath << "\"\n" + << indent << " NEW_RPATH \"" << newRpath << "\")\n"; + } } } @@ -681,9 +717,9 @@ cmInstallTargetGenerator::AddStripRule(std::ostream& os, const std::string& toDestDirPath) { - // don't strip static libraries, because it removes the only symbol table - // they have so you can't link to them anymore - if(this->Target->GetType() == cmTarget::STATIC_LIBRARY) + // don't strip static and import libraries, because it removes the only + // symbol table they have so you can't link to them anymore + if(this->Target->GetType()==cmTarget::STATIC_LIBRARY || this->ImportLibrary) { return; } diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 36d84f3be..898f379ad 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -22,45 +22,58 @@ # pragma warn -8060 /* possibly incorrect assignment */ #endif -bool cmListFileCacheParseFunction(cmListFileLexer* lexer, - cmListFileFunction& function, - const char* filename); +//---------------------------------------------------------------------------- +struct cmListFileParser +{ + cmListFileParser(cmListFile* lf, cmMakefile* mf, const char* filename); + ~cmListFileParser(); + bool ParseFile(); + bool ParseFunction(const char* name, long line); + void AddArgument(cmListFileLexer_Token* token, + cmListFileArgument::Delimiter delim); + cmListFile* ListFile; + cmMakefile* Makefile; + const char* FileName; + cmListFileLexer* Lexer; + cmListFileFunction Function; + enum { SeparationOkay, SeparationWarning } Separation; +}; -bool cmListFile::ParseFile(const char* filename, - bool topLevel, - cmMakefile *mf) +//---------------------------------------------------------------------------- +cmListFileParser::cmListFileParser(cmListFile* lf, cmMakefile* mf, + const char* filename): + ListFile(lf), Makefile(mf), FileName(filename), + Lexer(cmListFileLexer_New()) { - if(!cmSystemTools::FileExists(filename)) - { - return false; - } +} - // Create the scanner. - cmListFileLexer* lexer = cmListFileLexer_New(); - if(!lexer) - { - cmSystemTools::Error("cmListFileCache: error allocating lexer "); - return false; - } +//---------------------------------------------------------------------------- +cmListFileParser::~cmListFileParser() +{ + cmListFileLexer_Delete(this->Lexer); +} +//---------------------------------------------------------------------------- +bool cmListFileParser::ParseFile() +{ // Open the file. - if(!cmListFileLexer_SetFileName(lexer, filename)) + if(!cmListFileLexer_SetFileName(this->Lexer, this->FileName)) { - cmListFileLexer_Delete(lexer); cmSystemTools::Error("cmListFileCache: error can not open file ", - filename); + this->FileName); return false; } // Use a simple recursive-descent parser to process the token // stream. - this->ModifiedTime = cmSystemTools::ModifiedTime(filename); - bool parseError = false; bool haveNewline = true; - cmListFileLexer_Token* token; - while(!parseError && (token = cmListFileLexer_Scan(lexer))) + while(cmListFileLexer_Token* token = + cmListFileLexer_Scan(this->Lexer)) { - if(token->type == cmListFileLexer_Token_Newline) + if(token->type == cmListFileLexer_Token_Space) + { + } + else if(token->type == cmListFileLexer_Token_Newline) { haveNewline = true; } @@ -69,51 +82,66 @@ bool cmListFile::ParseFile(const char* filename, if(haveNewline) { haveNewline = false; - cmListFileFunction inFunction; - inFunction.Name = token->text; - inFunction.FilePath = filename; - inFunction.Line = token->line; - if(cmListFileCacheParseFunction(lexer, inFunction, filename)) + if(this->ParseFunction(token->text, token->line)) { - this->Functions.push_back(inFunction); + this->ListFile->Functions.push_back(this->Function); } else { - parseError = true; + return false; } } else { cmOStringStream error; error << "Error in cmake code at\n" - << filename << ":" << token->line << ":\n" + << this->FileName << ":" << token->line << ":\n" << "Parse error. Expected a newline, got " - << cmListFileLexer_GetTypeAsString(lexer, token->type) + << cmListFileLexer_GetTypeAsString(this->Lexer, token->type) << " with text \"" << token->text << "\"."; cmSystemTools::Error(error.str().c_str()); - parseError = true; + return false; } } else { cmOStringStream error; error << "Error in cmake code at\n" - << filename << ":" << token->line << ":\n" + << this->FileName << ":" << token->line << ":\n" << "Parse error. Expected a command name, got " - << cmListFileLexer_GetTypeAsString(lexer, token->type) + << cmListFileLexer_GetTypeAsString(this->Lexer, token->type) << " with text \"" << token->text << "\"."; cmSystemTools::Error(error.str().c_str()); - parseError = true; + return false; } } - if (parseError) + return true; +} + +//---------------------------------------------------------------------------- +bool cmListFile::ParseFile(const char* filename, + bool topLevel, + cmMakefile *mf) +{ + if(!cmSystemTools::FileExists(filename)) + { + return false; + } + + bool parseError = false; + this->ModifiedTime = cmSystemTools::ModifiedTime(filename); + + { + cmListFileParser parser(this, mf, filename); + parseError = !parser.ParseFile(); + } + + if(parseError) { this->ModifiedTime = 0; } - cmListFileLexer_Delete(lexer); - // do we need a cmake_policy(VERSION call? if(topLevel) { @@ -196,7 +224,8 @@ bool cmListFile::ParseFile(const char* filename, { cmListFileFunction project; project.Name = "PROJECT"; - cmListFileArgument prj("Project", false, filename, 0); + cmListFileArgument prj("Project", cmListFileArgument::Unquoted, + filename, 0); project.Arguments.push_back(prj); this->Functions.insert(this->Functions.begin(),project); } @@ -208,17 +237,24 @@ bool cmListFile::ParseFile(const char* filename, return true; } -bool cmListFileCacheParseFunction(cmListFileLexer* lexer, - cmListFileFunction& function, - const char* filename) +//---------------------------------------------------------------------------- +bool cmListFileParser::ParseFunction(const char* name, long line) { + // Inintialize a new function call. + this->Function = cmListFileFunction(); + this->Function.FilePath = this->FileName; + this->Function.Name = name; + this->Function.Line = line; + // Command name has already been parsed. Read the left paren. cmListFileLexer_Token* token; - if(!(token = cmListFileLexer_Scan(lexer))) + while((token = cmListFileLexer_Scan(this->Lexer)) && + token->type == cmListFileLexer_Token_Space) {} + if(!token) { cmOStringStream error; - error << "Error in cmake code at\n" - << filename << ":" << cmListFileLexer_GetCurrentLine(lexer) << ":\n" + error << "Error in cmake code at\n" << this->FileName << ":" + << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n" << "Parse error. Function missing opening \"(\"."; cmSystemTools::Error(error.str().c_str()); return false; @@ -226,26 +262,33 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer, if(token->type != cmListFileLexer_Token_ParenLeft) { cmOStringStream error; - error << "Error in cmake code at\n" - << filename << ":" << cmListFileLexer_GetCurrentLine(lexer) << ":\n" + error << "Error in cmake code at\n" << this->FileName << ":" + << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n" << "Parse error. Expected \"(\", got " - << cmListFileLexer_GetTypeAsString(lexer, token->type) + << cmListFileLexer_GetTypeAsString(this->Lexer, token->type) << " with text \"" << token->text << "\"."; cmSystemTools::Error(error.str().c_str()); return false; } // Arguments. - unsigned long lastLine = cmListFileLexer_GetCurrentLine(lexer); + unsigned long lastLine; unsigned long parenDepth = 0; - while((token = cmListFileLexer_Scan(lexer))) + this->Separation = SeparationOkay; + while((lastLine = cmListFileLexer_GetCurrentLine(this->Lexer), + token = cmListFileLexer_Scan(this->Lexer))) { + if(token->type == cmListFileLexer_Token_Space || + token->type == cmListFileLexer_Token_Newline) + { + this->Separation = SeparationOkay; + continue; + } if(token->type == cmListFileLexer_Token_ParenLeft) { parenDepth++; - cmListFileArgument a("(", - false, filename, token->line); - function.Arguments.push_back(a); + this->Separation = SeparationOkay; + this->AddArgument(token, cmListFileArgument::Unquoted); } else if(token->type == cmListFileLexer_Token_ParenRight) { @@ -254,43 +297,39 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer, return true; } parenDepth--; - cmListFileArgument a(")", - false, filename, token->line); - function.Arguments.push_back(a); + this->Separation = SeparationOkay; + this->AddArgument(token, cmListFileArgument::Unquoted); + this->Separation = SeparationWarning; } else if(token->type == cmListFileLexer_Token_Identifier || token->type == cmListFileLexer_Token_ArgumentUnquoted) { - cmListFileArgument a(token->text, - false, filename, token->line); - function.Arguments.push_back(a); + this->AddArgument(token, cmListFileArgument::Unquoted); + this->Separation = SeparationWarning; } else if(token->type == cmListFileLexer_Token_ArgumentQuoted) { - cmListFileArgument a(token->text, - true, filename, token->line); - function.Arguments.push_back(a); + this->AddArgument(token, cmListFileArgument::Quoted); + this->Separation = SeparationWarning; } - else if(token->type != cmListFileLexer_Token_Newline) + else { // Error. cmOStringStream error; - error << "Error in cmake code at\n" - << filename << ":" << cmListFileLexer_GetCurrentLine(lexer) - << ":\n" + error << "Error in cmake code at\n" << this->FileName << ":" + << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n" << "Parse error. Function missing ending \")\". " << "Instead found " - << cmListFileLexer_GetTypeAsString(lexer, token->type) + << cmListFileLexer_GetTypeAsString(this->Lexer, token->type) << " with text \"" << token->text << "\"."; cmSystemTools::Error(error.str().c_str()); return false; } - lastLine = cmListFileLexer_GetCurrentLine(lexer); } cmOStringStream error; error << "Error in cmake code at\n" - << filename << ":" << lastLine << ":\n" + << this->FileName << ":" << lastLine << ":\n" << "Parse error. Function missing ending \")\". " << "End of file reached."; cmSystemTools::Error(error.str().c_str()); @@ -299,6 +338,45 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer, } //---------------------------------------------------------------------------- +void cmListFileParser::AddArgument(cmListFileLexer_Token* token, + cmListFileArgument::Delimiter delim) +{ + cmListFileArgument a(token->text, delim, this->FileName, token->line); + this->Function.Arguments.push_back(a); + if(delim == cmListFileArgument::Unquoted) + { + // Warn about a future behavior change. + const char* c = a.Value.c_str(); + if(*c++ == '[') + { + while(*c == '=') + { ++c; } + if(*c == '[') + { + cmOStringStream m; + m << "Syntax Warning in cmake code at\n" + << " " << this->FileName << ":" << token->line << ":" + << token->column << "\n" + << "A future version of CMake may treat unquoted argument:\n" + << " " << a.Value << "\n" + << "as an opening long bracket. Double-quote the argument."; + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str().c_str()); + } + } + } + if(this->Separation == SeparationOkay) + { + return; + } + cmOStringStream m; + m << "Syntax Warning in cmake code at\n" + << " " << this->FileName << ":" << token->line << ":" + << token->column << "\n" + << "Argument not separated from preceding token by whitespace."; + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str().c_str()); +} + +//---------------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc) { os << lfc.FilePath; diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index fec3d07d8..7bb3b346c 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -25,22 +25,27 @@ class cmMakefile; struct cmListFileArgument { - cmListFileArgument(): Value(), Quoted(false), FilePath(0), Line(0) {} + enum Delimiter + { + Unquoted, + Quoted + }; + cmListFileArgument(): Value(), Delim(Unquoted), FilePath(0), Line(0) {} cmListFileArgument(const cmListFileArgument& r): - Value(r.Value), Quoted(r.Quoted), FilePath(r.FilePath), Line(r.Line) {} - cmListFileArgument(const std::string& v, bool q, const char* file, - long line): Value(v), Quoted(q), + Value(r.Value), Delim(r.Delim), FilePath(r.FilePath), Line(r.Line) {} + cmListFileArgument(const std::string& v, Delimiter d, const char* file, + long line): Value(v), Delim(d), FilePath(file), Line(line) {} bool operator == (const cmListFileArgument& r) const { - return (this->Value == r.Value) && (this->Quoted == r.Quoted); + return (this->Value == r.Value) && (this->Delim == r.Delim); } bool operator != (const cmListFileArgument& r) const { return !(*this == r); } std::string Value; - bool Quoted; + Delimiter Delim; const char* FilePath; long Line; }; diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c index b6424d60e..2841fe511 100644 --- a/Source/cmListFileLexer.c +++ b/Source/cmListFileLexer.c @@ -9,7 +9,7 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 31 +#define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -31,7 +31,15 @@ /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ -#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + #include <inttypes.h> typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; @@ -46,7 +54,6 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -77,6 +84,8 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif +#endif /* ! C99 */ + #endif /* ! FLEXINT_H */ #ifdef __cplusplus @@ -86,11 +95,12 @@ typedef unsigned int flex_uint32_t; #else /* ! __cplusplus */ -#if __STDC__ +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) #define YY_USE_CONST -#endif /* __STDC__ */ +#endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST @@ -126,8 +136,6 @@ typedef void* yyscan_t; #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) #define yy_flex_debug yyg->yy_flex_debug_r -int cmListFileLexer_yylex_init (yyscan_t* scanner); - /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. @@ -151,9 +159,21 @@ int cmListFileLexer_yylex_init (yyscan_t* scanner); /* Size of default input buffer. */ #ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else #define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ #endif +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; @@ -192,14 +212,9 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE; } \ while ( 0 ) -/* The following is because we cannot portably get our hands on size_t - * (without autoconf's help, which isn't available because we want - * flex-generated scanners to compile on their own). - */ - #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T -typedef unsigned int yy_size_t; +typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE @@ -354,8 +369,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 14 -#define YY_END_OF_BUFFER 15 +#define YY_NUM_RULES 16 +#define YY_END_OF_BUFFER 17 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -363,12 +378,13 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[39] = +static yyconst flex_int16_t yy_accept[45] = { 0, - 0, 0, 0, 0, 15, 6, 12, 1, 7, 2, - 6, 3, 4, 6, 13, 8, 9, 10, 11, 6, - 0, 6, 0, 2, 0, 5, 6, 8, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 17, 6, 14, 1, 8, 2, + 6, 3, 4, 6, 15, 9, 11, 12, 13, 6, + 0, 6, 0, 14, 2, 0, 5, 6, 9, 0, + 10, 0, 7, 0, 0, 0, 7, 0, 7, 0, + 0, 0, 0, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -405,64 +421,70 @@ static yyconst flex_int32_t yy_ec[256] = static yyconst flex_int32_t yy_meta[13] = { 0, - 1, 1, 2, 1, 3, 1, 1, 1, 4, 4, - 4, 1 + 1, 2, 3, 2, 4, 1, 1, 1, 5, 5, + 5, 1 } ; -static yyconst flex_int16_t yy_base[48] = +static yyconst flex_int16_t yy_base[56] = { 0, - 0, 0, 10, 20, 34, 32, 89, 89, 89, 0, - 23, 89, 89, 35, 0, 18, 89, 89, 44, 0, - 49, 21, 0, 0, 19, 0, 0, 15, 59, 0, - 18, 0, 15, 12, 11, 10, 9, 89, 64, 68, - 72, 76, 80, 13, 84, 12, 10 + 0, 0, 10, 20, 38, 32, 0, 109, 109, 0, + 28, 109, 109, 35, 0, 23, 109, 109, 44, 0, + 49, 26, 0, 0, 0, 22, 0, 0, 18, 24, + 109, 0, 61, 20, 0, 18, 0, 17, 16, 0, + 12, 11, 10, 109, 73, 16, 78, 83, 88, 93, + 12, 98, 11, 103, 9 } ; -static yyconst flex_int16_t yy_def[48] = +static yyconst flex_int16_t yy_def[56] = { 0, - 38, 1, 39, 39, 38, 38, 38, 38, 38, 40, - 6, 38, 38, 6, 41, 42, 38, 38, 42, 6, - 38, 6, 43, 40, 44, 14, 6, 42, 42, 21, - 21, 45, 46, 44, 47, 46, 47, 0, 38, 38, - 38, 38, 38, 38, 38, 38, 38 + 44, 1, 45, 45, 44, 44, 46, 44, 44, 47, + 6, 44, 44, 6, 48, 49, 44, 44, 49, 6, + 44, 6, 50, 46, 47, 51, 14, 6, 49, 49, + 44, 21, 44, 21, 52, 53, 33, 51, 33, 54, + 55, 53, 55, 0, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44 } ; -static yyconst flex_int16_t yy_nxt[102] = +static yyconst flex_int16_t yy_nxt[122] = { 0, 6, 7, 8, 7, 9, 10, 11, 12, 13, 6, - 14, 15, 17, 37, 18, 36, 34, 30, 20, 30, - 27, 19, 17, 20, 18, 35, 29, 27, 33, 29, - 25, 19, 20, 38, 38, 38, 21, 38, 22, 38, - 38, 20, 20, 23, 26, 26, 28, 38, 28, 30, - 30, 38, 38, 20, 38, 31, 38, 38, 30, 30, - 32, 28, 38, 28, 16, 16, 16, 16, 24, 38, - 24, 24, 27, 38, 27, 27, 28, 38, 38, 28, - 20, 38, 20, 20, 30, 38, 30, 30, 5, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - - 38 + 14, 15, 17, 43, 18, 42, 38, 24, 32, 33, + 32, 19, 17, 36, 18, 37, 33, 41, 29, 30, + 37, 19, 20, 36, 30, 26, 21, 44, 22, 44, + 44, 20, 20, 23, 27, 27, 31, 44, 29, 32, + 32, 44, 44, 33, 44, 34, 44, 44, 32, 32, + 35, 33, 44, 44, 44, 21, 44, 39, 44, 44, + 33, 33, 40, 16, 16, 16, 16, 16, 25, 25, + 44, 25, 25, 28, 28, 44, 28, 28, 29, 29, + 44, 44, 29, 20, 20, 44, 20, 20, 32, 32, + + 44, 32, 32, 33, 33, 44, 33, 33, 5, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44 } ; -static yyconst flex_int16_t yy_chk[102] = +static yyconst flex_int16_t yy_chk[122] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 3, 47, 3, 46, 44, 37, 36, 35, - 34, 3, 4, 33, 4, 31, 28, 25, 22, 16, - 11, 4, 6, 5, 0, 0, 6, 0, 6, 0, + 1, 1, 3, 55, 3, 53, 51, 46, 43, 42, + 41, 3, 4, 39, 4, 38, 36, 34, 30, 29, + 26, 4, 6, 22, 16, 11, 6, 5, 6, 0, 0, 6, 6, 6, 14, 14, 19, 0, 19, 21, 21, 0, 0, 21, 0, 21, 0, 0, 21, 21, - 21, 29, 0, 29, 39, 39, 39, 39, 40, 0, - 40, 40, 41, 0, 41, 41, 42, 0, 0, 42, - 43, 0, 43, 43, 45, 0, 45, 45, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - - 38 + 21, 33, 0, 0, 0, 33, 0, 33, 0, 0, + 33, 33, 33, 45, 45, 45, 45, 45, 47, 47, + 0, 47, 47, 48, 48, 0, 48, 48, 49, 49, + 0, 0, 49, 50, 50, 0, 50, 50, 52, 52, + + 0, 52, 52, 54, 54, 0, 54, 54, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[15] = +static yyconst flex_int32_t yy_rule_can_match_eol[17] = { 0, -1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, }; +1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -494,9 +516,11 @@ Run flex like this: Modify cmListFileLexer.c: - remove TABs + - remove use of the 'register' storage class specifier - remove the yyunput function - add a statement "(void)yyscanner;" to the top of these methods: yy_fatal_error, cmListFileLexer_yyalloc, cmListFileLexer_yyrealloc, cmListFileLexer_yyfree + - remove statement "yyscanner = NULL;" from cmListFileLexer_yylex_destroy - remove all YY_BREAK lines occurring right after return statements - remove the isatty forward declaration @@ -540,7 +564,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer); /*--------------------------------------------------------------------------*/ -#line 568 "cmListFileLexer.c" +#line 570 "cmListFileLexer.c" #define INITIAL 0 #define STRING 1 @@ -591,6 +615,12 @@ struct yyguts_t }; /* end struct yyguts_t */ +static int yy_init_globals (yyscan_t yyscanner ); + +int cmListFileLexer_yylex_init (yyscan_t* scanner); + +int cmListFileLexer_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ @@ -620,6 +650,10 @@ int cmListFileLexer_yyget_lineno (yyscan_t yyscanner ); void cmListFileLexer_yyset_lineno (int line_number ,yyscan_t yyscanner ); +int cmListFileLexer_yyget_column (yyscan_t yyscanner ); + +void cmListFileLexer_yyset_column (int column_no ,yyscan_t yyscanner ); + /* Macros after this point can all be overridden by user definitions in * section 1. */ @@ -652,7 +686,12 @@ static int input (yyscan_t yyscanner ); /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else #define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ @@ -660,7 +699,7 @@ static int input (yyscan_t yyscanner ); /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ -#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, @@ -749,19 +788,19 @@ extern int cmListFileLexer_yylex (yyscan_t yyscanner); */ YY_DECL { - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 100 "cmListFileLexer.in.l" +#line 82 "cmListFileLexer.in.l" -#line 787 "cmListFileLexer.c" +#line 804 "cmListFileLexer.c" - if ( yyg->yy_init ) + if ( !yyg->yy_init ) { - yyg->yy_init = 0; + yyg->yy_init = 1; #ifdef YY_USER_INIT YY_USER_INIT; @@ -801,7 +840,7 @@ YY_DECL yy_match: do { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -810,13 +849,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 39 ) + if ( yy_current_state >= 45 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 89 ); + while ( yy_base[yy_current_state] != 109 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -855,7 +894,7 @@ do_action: /* This label is used only to access EOF actions. */ case 1: /* rule 1 can match eol */ YY_RULE_SETUP -#line 102 "cmListFileLexer.in.l" +#line 84 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_Newline; cmListFileLexerSetToken(lexer, yytext, yyleng); @@ -865,14 +904,14 @@ YY_RULE_SETUP } case 2: YY_RULE_SETUP -#line 110 "cmListFileLexer.in.l" +#line 92 "cmListFileLexer.in.l" { lexer->column += yyleng; } YY_BREAK case 3: YY_RULE_SETUP -#line 114 "cmListFileLexer.in.l" +#line 96 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_ParenLeft; cmListFileLexerSetToken(lexer, yytext, yyleng); @@ -881,7 +920,7 @@ YY_RULE_SETUP } case 4: YY_RULE_SETUP -#line 121 "cmListFileLexer.in.l" +#line 103 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_ParenRight; cmListFileLexerSetToken(lexer, yytext, yyleng); @@ -890,7 +929,7 @@ YY_RULE_SETUP } case 5: YY_RULE_SETUP -#line 128 "cmListFileLexer.in.l" +#line 110 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_Identifier; cmListFileLexerSetToken(lexer, yytext, yyleng); @@ -899,7 +938,7 @@ YY_RULE_SETUP } case 6: YY_RULE_SETUP -#line 135 "cmListFileLexer.in.l" +#line 117 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted; cmListFileLexerSetToken(lexer, yytext, yyleng); @@ -908,7 +947,16 @@ YY_RULE_SETUP } case 7: YY_RULE_SETUP -#line 142 "cmListFileLexer.in.l" +#line 124 "cmListFileLexer.in.l" +{ + lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} +case 8: +YY_RULE_SETUP +#line 131 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_ArgumentQuoted; cmListFileLexerSetToken(lexer, "", 0); @@ -916,58 +964,69 @@ YY_RULE_SETUP BEGIN(STRING); } YY_BREAK -case 8: -/* rule 8 can match eol */ +case 9: YY_RULE_SETUP -#line 149 "cmListFileLexer.in.l" +#line 138 "cmListFileLexer.in.l" { cmListFileLexerAppend(lexer, yytext, yyleng); lexer->column += yyleng; } YY_BREAK -case 9: -/* rule 9 can match eol */ +case 10: +/* rule 10 can match eol */ YY_RULE_SETUP -#line 154 "cmListFileLexer.in.l" +#line 143 "cmListFileLexer.in.l" { cmListFileLexerAppend(lexer, yytext, yyleng); ++lexer->line; lexer->column = 1; } YY_BREAK -case 10: +case 11: +/* rule 11 can match eol */ +YY_RULE_SETUP +#line 149 "cmListFileLexer.in.l" +{ + cmListFileLexerAppend(lexer, yytext, yyleng); + ++lexer->line; + lexer->column = 1; +} + YY_BREAK +case 12: YY_RULE_SETUP -#line 160 "cmListFileLexer.in.l" +#line 155 "cmListFileLexer.in.l" { lexer->column += yyleng; BEGIN(INITIAL); return 1; } -case 11: +case 13: YY_RULE_SETUP -#line 166 "cmListFileLexer.in.l" +#line 161 "cmListFileLexer.in.l" { cmListFileLexerAppend(lexer, yytext, yyleng); lexer->column += yyleng; } YY_BREAK case YY_STATE_EOF(STRING): -#line 171 "cmListFileLexer.in.l" +#line 166 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_BadString; BEGIN(INITIAL); return 1; } -case 12: +case 14: YY_RULE_SETUP -#line 177 "cmListFileLexer.in.l" +#line 172 "cmListFileLexer.in.l" { + lexer->token.type = cmListFileLexer_Token_Space; + cmListFileLexerSetToken(lexer, yytext, yyleng); lexer->column += yyleng; + return 1; } - YY_BREAK -case 13: +case 15: YY_RULE_SETUP -#line 181 "cmListFileLexer.in.l" +#line 179 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_BadCharacter; cmListFileLexerSetToken(lexer, yytext, yyleng); @@ -975,18 +1034,18 @@ YY_RULE_SETUP return 1; } case YY_STATE_EOF(INITIAL): -#line 188 "cmListFileLexer.in.l" +#line 186 "cmListFileLexer.in.l" { lexer->token.type = cmListFileLexer_Token_None; cmListFileLexerSetToken(lexer, 0, 0); return 0; } -case 14: +case 16: YY_RULE_SETUP -#line 194 "cmListFileLexer.in.l" +#line 192 "cmListFileLexer.in.l" ECHO; YY_BREAK -#line 1025 "cmListFileLexer.c" +#line 1064 "cmListFileLexer.c" case YY_END_OF_BUFFER: { @@ -1127,9 +1186,9 @@ ECHO; static int yy_get_next_buffer (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = yyg->yytext_ptr; - register int number_to_move, i; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = yyg->yytext_ptr; + int number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) @@ -1171,7 +1230,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else { - size_t num_to_read = + int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) @@ -1216,7 +1275,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - yyg->yy_n_chars, num_to_read ); + yyg->yy_n_chars, (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; } @@ -1240,6 +1299,14 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else ret_val = EOB_ACT_CONTINUE_SCAN; + if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmListFileLexer_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + yyg->yy_n_chars += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; @@ -1253,15 +1320,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner) static yy_state_type yy_get_previous_state (yyscan_t yyscanner) { - register yy_state_type yy_current_state; - register char *yy_cp; + yy_state_type yy_current_state; + char *yy_cp; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_current_state = yyg->yy_start; for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1270,7 +1337,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 39 ) + if ( yy_current_state >= 45 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1286,11 +1353,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) { - register int yy_is_jam; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - register char *yy_cp = yyg->yy_c_buf_p; + int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + char *yy_cp = yyg->yy_c_buf_p; - register YY_CHAR yy_c = 1; + YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1299,11 +1366,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 39 ) + if ( yy_current_state >= 45 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 38); + yy_is_jam = (yy_current_state == 44); return yy_is_jam ? 0 : yy_current_state; } @@ -1633,6 +1700,8 @@ static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner) yyg->yy_buffer_stack = (struct yy_buffer_state**)cmListFileLexer_yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" ); memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); @@ -1651,6 +1720,8 @@ static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner) (yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); @@ -1695,26 +1766,26 @@ YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer (char * base, yy_size_t size , /** Setup the input buffer state to scan a string. The next call to cmListFileLexer_yylex() will * scan from a @e copy of @a str. - * @param str a NUL-terminated string to scan + * @param yystr a NUL-terminated string to scan * @param yyscanner The scanner object. * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * cmListFileLexer_yy_scan_bytes() instead. */ -YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yy_str , yyscan_t yyscanner) +YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) { - return cmListFileLexer_yy_scan_bytes(yy_str,strlen(yy_str) ,yyscanner); + return cmListFileLexer_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); } /** Setup the input buffer state to scan the given bytes. The next call to cmListFileLexer_yylex() will * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * bytes, int len , yyscan_t yyscanner) +YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; @@ -1722,15 +1793,15 @@ YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * bytes, int len , int i; /* Get memory for full buffer, including space for trailing EOB's. */ - n = len + 2; + n = _yybytes_len + 2; buf = (char *) cmListFileLexer_yyalloc(n ,yyscanner ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_bytes()" ); - for ( i = 0; i < len; ++i ) - buf[i] = bytes[i]; + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; - buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = cmListFileLexer_yy_scan_buffer(buf,n ,yyscanner); if ( ! b ) @@ -1918,21 +1989,87 @@ void cmListFileLexer_yyset_debug (int bdebug , yyscan_t yyscanner) /* Accessor methods for yylval and yylloc */ +/* User-visible API */ + +/* cmListFileLexer_yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ + +int cmListFileLexer_yylex_init(yyscan_t* ptr_yy_globals) + +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* cmListFileLexer_yylex_init_extra has the same functionality as cmListFileLexer_yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to cmListFileLexer_yyalloc in + * the yyextra field. + */ + +int cmListFileLexer_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) + +{ + struct yyguts_t dummy_yyguts; + + cmListFileLexer_yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + cmListFileLexer_yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + static int yy_init_globals (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Initialization is the same as for the non-reentrant scanner. - This function is called once per scanner lifetime. */ + * This function is called from cmListFileLexer_yylex_destroy(), so don't allocate here. + */ yyg->yy_buffer_stack = 0; yyg->yy_buffer_stack_top = 0; yyg->yy_buffer_stack_max = 0; yyg->yy_c_buf_p = (char *) 0; - yyg->yy_init = 1; + yyg->yy_init = 0; yyg->yy_start = 0; + yyg->yy_start_stack_ptr = 0; yyg->yy_start_stack_depth = 0; - yyg->yy_start_stack = (int *) 0; + yyg->yy_start_stack = NULL; /* Defined in main.c */ #ifdef YY_STDINIT @@ -1949,33 +2086,6 @@ static int yy_init_globals (yyscan_t yyscanner) return 0; } -/* User-visible API */ - -/* cmListFileLexer_yylex_init is special because it creates the scanner itself, so it is - * the ONLY reentrant function that doesn't take the scanner as the last argument. - * That's why we explicitly handle the declaration, instead of using our macros. - */ - -int cmListFileLexer_yylex_init(yyscan_t* ptr_yy_globals) - -{ - if (ptr_yy_globals == NULL){ - errno = EINVAL; - return 1; - } - - *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), NULL ); - - if (*ptr_yy_globals == NULL){ - errno = ENOMEM; - return 1; - } - - memset(*ptr_yy_globals,0,sizeof(struct yyguts_t)); - - return yy_init_globals ( *ptr_yy_globals ); -} - /* cmListFileLexer_yylex_destroy is for both reentrant and non-reentrant scanners. */ int cmListFileLexer_yylex_destroy (yyscan_t yyscanner) { @@ -1996,6 +2106,10 @@ int cmListFileLexer_yylex_destroy (yyscan_t yyscanner) cmListFileLexer_yyfree(yyg->yy_start_stack ,yyscanner ); yyg->yy_start_stack = NULL; + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * cmListFileLexer_yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + /* Destroy the main struct (reentrant only). */ cmListFileLexer_yyfree ( yyscanner , yyscanner ); return 0; @@ -2008,8 +2122,7 @@ int cmListFileLexer_yylex_destroy (yyscan_t yyscanner) #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) { - register int i; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } @@ -2018,8 +2131,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) { - register int n; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + int n; for ( n = 0; s[n]; ++n ) ; @@ -2054,19 +2166,7 @@ void cmListFileLexer_yyfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#undef YY_NEW_FILE -#undef YY_FLUSH_BUFFER -#undef yy_set_bol -#undef yy_new_buffer -#undef yy_set_interactive -#undef yytext_ptr -#undef YY_DO_BEFORE_ACTION - -#ifdef YY_DECL_IS_OURS -#undef YY_DECL_IS_OURS -#undef YY_DECL -#endif -#line 194 "cmListFileLexer.in.l" +#line 192 "cmListFileLexer.in.l" @@ -2122,7 +2222,7 @@ static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text, } /* We need to extend the buffer. */ - temp = (char*)malloc(newSize); + temp = malloc(newSize); if(lexer->token.text) { memcpy(temp, lexer->token.text, lexer->token.length); @@ -2303,6 +2403,7 @@ const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer, switch(type) { case cmListFileLexer_Token_None: return "nothing"; + case cmListFileLexer_Token_Space: return "space"; case cmListFileLexer_Token_Newline: return "newline"; case cmListFileLexer_Token_Identifier: return "identifier"; case cmListFileLexer_Token_ParenLeft: return "left paren"; diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h index 5f4db33c4..cc78b5c2f 100644 --- a/Source/cmListFileLexer.h +++ b/Source/cmListFileLexer.h @@ -15,6 +15,7 @@ typedef enum cmListFileLexer_Type_e { cmListFileLexer_Token_None, + cmListFileLexer_Token_Space, cmListFileLexer_Token_Newline, cmListFileLexer_Token_Identifier, cmListFileLexer_Token_ParenLeft, diff --git a/Source/cmListFileLexer.in.l b/Source/cmListFileLexer.in.l index 41e817b1a..12b53eef6 100644 --- a/Source/cmListFileLexer.in.l +++ b/Source/cmListFileLexer.in.l @@ -20,9 +20,11 @@ Run flex like this: Modify cmListFileLexer.c: - remove TABs + - remove use of the 'register' storage class specifier - remove the yyunput function - add a statement "(void)yyscanner;" to the top of these methods: yy_fatal_error, cmListFileLexer_yyalloc, cmListFileLexer_yyrealloc, cmListFileLexer_yyfree + - remove statement "yyscanner = NULL;" from cmListFileLexer_yylex_destroy - remove all YY_BREAK lines occurring right after return statements - remove the isatty forward declaration @@ -74,6 +76,8 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer); %x STRING MAKEVAR \$\([A-Za-z0-9_]*\) +UNQUOTED ([^ \t\r\n\(\)#\\\"]|\\.) +LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t])*\" %% @@ -110,7 +114,14 @@ MAKEVAR \$\([A-Za-z0-9_]*\) return 1; } -({MAKEVAR}|[^ \t\r\n\(\)#\\\"]|\\.)({MAKEVAR}|[^ \t\r\n\(\)#\\\"]|\\.|\"({MAKEVAR}|[^\r\n\(\)#\\\"]|\\.)*\")* { +({UNQUOTED})({UNQUOTED})* { + lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} + +({MAKEVAR}|{UNQUOTED})({LEGACY})* { lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted; cmListFileLexerSetToken(lexer, yytext, yyleng); lexer->column += yyleng; @@ -124,11 +135,17 @@ MAKEVAR \$\([A-Za-z0-9_]*\) BEGIN(STRING); } -<STRING>([^\\\n\"]|\\(.|\n))+ { +<STRING>([^\\\n\"]|\\.)+ { cmListFileLexerAppend(lexer, yytext, yyleng); lexer->column += yyleng; } +<STRING>\\\n { + cmListFileLexerAppend(lexer, yytext, yyleng); + ++lexer->line; + lexer->column = 1; +} + <STRING>\n { cmListFileLexerAppend(lexer, yytext, yyleng); ++lexer->line; @@ -152,8 +169,11 @@ MAKEVAR \$\([A-Za-z0-9_]*\) return 1; } -[ \t\r] { +[ \t\r]+ { + lexer->token.type = cmListFileLexer_Token_Space; + cmListFileLexerSetToken(lexer, yytext, yyleng); lexer->column += yyleng; + return 1; } . { @@ -404,6 +424,7 @@ const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer, switch(type) { case cmListFileLexer_Token_None: return "nothing"; + case cmListFileLexer_Token_Space: return "space"; case cmListFileLexer_Token_Newline: return "newline"; case cmListFileLexer_Token_Identifier: return "identifier"; case cmListFileLexer_Token_ParenLeft: return "left paren"; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index ee5b9d812..9c0410965 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -55,7 +55,6 @@ cmLocalGenerator::cmLocalGenerator() this->UseRelativePaths = false; this->Configured = false; this->EmitUniversalBinaryFlags = true; - this->IsMakefileGenerator = false; this->RelativePathsConfigured = false; this->PathConversionsSetup = false; this->BackwardsCompatibility = 0; @@ -260,12 +259,7 @@ void cmLocalGenerator::TraceDependencies() cmTargets& targets = this->Makefile->GetTargets(); for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) { - const char* projectFilename = 0; - if (this->IsMakefileGenerator == false) // only use of this variable - { - projectFilename = t->second.GetName(); - } - t->second.TraceDependencies(projectFilename); + t->second.TraceDependencies(); } } @@ -294,7 +288,7 @@ void cmLocalGenerator::GenerateTestFiles() << "# Build directory: " << this->Makefile->GetStartOutputDirectory() << std::endl << "# " << std::endl - << "# This file includes the relevent testing commands " + << "# This file includes the relevant testing commands " << "required for " << std::endl << "# testing this directory and lists subdirectories to " << "be tested as well." << std::endl; @@ -577,7 +571,7 @@ void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname, { std::vector<std::string> includes; this->GetIncludeDirectories(includes, &target, lang); - flags += this->GetIncludeFlags(includes, lang); + flags += this->GetIncludeFlags(includes, &target, lang); } flags += this->Makefile->GetDefineFlags(); @@ -761,7 +755,7 @@ void cmLocalGenerator if(!llang) { cmSystemTools::Error - ("CMake can not determine linker language for target:", + ("CMake can not determine linker language for target: ", target.Target->GetName()); return; } @@ -1084,8 +1078,6 @@ void cmLocalGenerator::ExpandRuleVariables(std::string& s, const RuleVariables& replaceValues) { - std::vector<std::string> enabledLanguages; - this->GlobalGenerator->GetEnabledLanguages(enabledLanguages); this->InsertRuleLauncher(s, replaceValues.CMTarget, replaceValues.RuleLauncher); std::string::size_type start = s.find('<'); @@ -1212,6 +1204,7 @@ cmLocalGenerator::ConvertToIncludeReference(std::string const& path) //---------------------------------------------------------------------------- std::string cmLocalGenerator::GetIncludeFlags( const std::vector<std::string> &includes, + cmGeneratorTarget* target, const char* lang, bool forResponseFile, const char *config) { @@ -1282,11 +1275,10 @@ std::string cmLocalGenerator::GetIncludeFlags( continue; } - std::string include = *i; if(!flagUsed || repeatFlag) { - if(sysIncludeFlag && - this->Makefile->IsSystemIncludeDirectory(i->c_str(), config)) + if(sysIncludeFlag && target && + target->IsSystemIncludeDirectory(i->c_str(), config)) { includeFlags << sysIncludeFlag; } @@ -1327,6 +1319,65 @@ std::string cmLocalGenerator::GetIncludeFlags( } //---------------------------------------------------------------------------- +void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines, + cmTarget* target, + const char* config) +{ + std::vector<std::string> targetDefines; + target->GetCompileDefinitions(targetDefines, + config); + this->AppendDefines(defines, targetDefines); +} + +//---------------------------------------------------------------------------- +void cmLocalGenerator::AddCompileOptions( + std::string& flags, cmTarget* target, + const char* lang, const char* config + ) +{ + std::string langFlagRegexVar = std::string("CMAKE_")+lang+"_FLAG_REGEX"; + if(const char* langFlagRegexStr = + this->Makefile->GetDefinition(langFlagRegexVar.c_str())) + { + // Filter flags acceptable to this language. + cmsys::RegularExpression r(langFlagRegexStr); + std::vector<std::string> opts; + if(const char* targetFlags = target->GetProperty("COMPILE_FLAGS")) + { + cmSystemTools::ParseWindowsCommandLine(targetFlags, opts); + } + target->GetCompileOptions(opts, config); + for(std::vector<std::string>::const_iterator i = opts.begin(); + i != opts.end(); ++i) + { + if(r.find(i->c_str())) + { + // (Re-)Escape this flag. COMPILE_FLAGS were already parsed + // as a command line above, and COMPILE_OPTIONS are escaped. + this->AppendFlagEscape(flags, i->c_str()); + } + } + } + else + { + // Use all flags. + if(const char* targetFlags = target->GetProperty("COMPILE_FLAGS")) + { + // COMPILE_FLAGS are not escaped for historical reasons. + this->AppendFlags(flags, targetFlags); + } + std::vector<std::string> opts; + target->GetCompileOptions(opts, config); + for(std::vector<std::string>::const_iterator i = opts.begin(); + i != opts.end(); ++i) + { + // COMPILE_OPTIONS are escaped. + this->AppendFlagEscape(flags, i->c_str()); + } + } +} + +//---------------------------------------------------------------------------- void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, cmGeneratorTarget* target, const char* lang, @@ -1476,6 +1527,25 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, } } +void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags, + std::string const& config, + cmTarget* target) +{ + this->AppendFlags(flags, + this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS")); + if(!config.empty()) + { + std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config; + this->AppendFlags(flags, this->Makefile->GetSafeDefinition(name.c_str())); + } + this->AppendFlags(flags, target->GetProperty("STATIC_LIBRARY_FLAGS")); + if(!config.empty()) + { + std::string name = "STATIC_LIBRARY_FLAGS_" + config; + this->AppendFlags(flags, target->GetProperty(name.c_str())); + } +} + void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, std::string& flags, std::string& linkFlags, @@ -1492,26 +1562,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, switch(target->GetType()) { case cmTarget::STATIC_LIBRARY: - { - const char* targetLinkFlags = - target->GetProperty("STATIC_LIBRARY_FLAGS"); - if(targetLinkFlags) - { - linkFlags += targetLinkFlags; - linkFlags += " "; - } - if(!buildType.empty()) - { - std::string build = "STATIC_LIBRARY_FLAGS_"; - build += buildType; - targetLinkFlags = target->GetProperty(build.c_str()); - if(targetLinkFlags) - { - linkFlags += targetLinkFlags; - linkFlags += " "; - } - } - } + this->GetStaticLibraryFlags(linkFlags, buildType, target->Target); break; case cmTarget::MODULE_LIBRARY: libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS"; @@ -1582,7 +1633,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, if(!linkLanguage) { cmSystemTools::Error - ("CMake can not determine linker language for target:", + ("CMake can not determine linker language for target: ", target->Target->GetName()); return; } @@ -1994,6 +2045,81 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags, } } +static void AddVisibilityCompileOption(std::string &flags, cmTarget* target, + cmLocalGenerator *lg, const char *lang) +{ + std::string l(lang); + std::string compileOption = "CMAKE_" + l + "_COMPILE_OPTIONS_VISIBILITY"; + const char *opt = lg->GetMakefile()->GetDefinition(compileOption.c_str()); + if (!opt) + { + return; + } + std::string flagDefine = l + "_VISIBILITY_PRESET"; + + const char *prop = target->GetProperty(flagDefine.c_str()); + if (!prop) + { + return; + } + if (strcmp(prop, "hidden") != 0 + && strcmp(prop, "default") != 0 + && strcmp(prop, "protected") != 0 + && strcmp(prop, "internal") != 0 ) + { + cmOStringStream e; + e << "Target " << target->GetName() << " uses unsupported value \"" + << prop << "\" for " << flagDefine << "."; + cmSystemTools::Error(e.str().c_str()); + return; + } + std::string option = std::string(opt) + prop; + lg->AppendFlags(flags, option.c_str()); +} + +static void AddInlineVisibilityCompileOption(std::string &flags, + cmTarget* target, + cmLocalGenerator *lg) +{ + std::string compileOption + = "CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN"; + const char *opt = lg->GetMakefile()->GetDefinition(compileOption.c_str()); + if (!opt) + { + return; + } + + bool prop = target->GetPropertyAsBool("VISIBILITY_INLINES_HIDDEN"); + if (!prop) + { + return; + } + lg->AppendFlags(flags, opt); +} + +//---------------------------------------------------------------------------- +void cmLocalGenerator +::AddVisibilityPresetFlags(std::string &flags, cmTarget* target, + const char *lang) +{ + int targetType = target->GetType(); + bool suitableTarget = ((targetType == cmTarget::SHARED_LIBRARY) + || (targetType == cmTarget::MODULE_LIBRARY) + || (target->IsExecutableWithExports())); + + if (!suitableTarget) + { + return; + } + + if (!lang) + { + return; + } + AddVisibilityCompileOption(flags, target, this, lang); + AddInlineVisibilityCompileOption(flags, target, this); +} + //---------------------------------------------------------------------------- void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target, std::string const& lang, @@ -2011,13 +2137,13 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target, else { if (target->GetType() == cmTarget::OBJECT_LIBRARY) - { + { if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE")) { this->AddPositionIndependentFlags(flags, lang, targetType); } return; - } + } if (target->GetLinkInterfaceDependentBoolProperty( "POSITION_INDEPENDENT_CODE", @@ -2105,7 +2231,7 @@ void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags, for(std::vector<std::string>::const_iterator oi = options.begin(); oi != options.end(); ++oi) { - this->AppendFlags(flags, this->EscapeForShell(oi->c_str()).c_str()); + this->AppendFlagEscape(flags, oi->c_str()); } } } @@ -2143,6 +2269,13 @@ void cmLocalGenerator::AppendFlags(std::string& flags, } //---------------------------------------------------------------------------- +void cmLocalGenerator::AppendFlagEscape(std::string& flags, + const char* rawFlag) +{ + this->AppendFlags(flags, this->EscapeForShell(rawFlag).c_str()); +} + +//---------------------------------------------------------------------------- void cmLocalGenerator::AppendDefines(std::set<std::string>& defines, const char* defines_list) { @@ -2155,7 +2288,13 @@ void cmLocalGenerator::AppendDefines(std::set<std::string>& defines, // Expand the list of definitions. std::vector<std::string> defines_vec; cmSystemTools::ExpandListArgument(defines_list, defines_vec); + this->AppendDefines(defines, defines_vec); +} +//---------------------------------------------------------------------------- +void cmLocalGenerator::AppendDefines(std::set<std::string>& defines, + const std::vector<std::string> &defines_vec) +{ for(std::vector<std::string>::const_iterator di = defines_vec.begin(); di != defines_vec.end(); ++di) { @@ -2248,7 +2387,7 @@ void cmLocalGenerator::AppendFeatureOptions( for(std::vector<std::string>::const_iterator oi = options.begin(); oi != options.end(); ++oi) { - this->AppendFlags(flags, this->EscapeForShell(oi->c_str()).c_str()); + this->AppendFlagEscape(flags, oi->c_str()); } } } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index a1c34f076..10f0b1a6c 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -143,12 +143,16 @@ public: const char* config); void AddCMP0018Flags(std::string &flags, cmTarget* target, std::string const& lang, const char *config); + void AddVisibilityPresetFlags(std::string &flags, cmTarget* target, + const char *lang); void AddConfigVariableFlags(std::string& flags, const char* var, const char* config); ///! Append flags to a string. virtual void AppendFlags(std::string& flags, const char* newFlags); + virtual void AppendFlagEscape(std::string& flags, const char* rawFlag); ///! Get the include flags for the current makefile and language std::string GetIncludeFlags(const std::vector<std::string> &includes, + cmGeneratorTarget* target, const char* lang, bool forResponseFile = false, const char *config = 0); @@ -163,6 +167,9 @@ public: { this->AppendDefines(defines, defines_list.c_str()); } + void AppendDefines(std::set<std::string>& defines, + const std::vector<std::string> &defines_vec); + /** * Join a set of defines into a definesString with a space separator. */ @@ -215,6 +222,10 @@ public: cmGeneratorTarget* target, const char* lang = "C", const char *config = 0, bool stripImplicitInclDirs = true); + void AddCompileOptions(std::string& flags, cmTarget* target, + const char* lang, const char* config); + void AddCompileDefinitions(std::set<std::string>& defines, cmTarget* target, + const char* config); /** Compute the language used to compile the given source file. */ const char* GetSourceFileLanguage(const cmSourceFile& source); @@ -337,6 +348,11 @@ public: std::string const& dir_max, bool* hasSourceExtension = 0); + /** Fill out the static linker flags for the given target. */ + void GetStaticLibraryFlags(std::string& flags, + std::string const& config, + cmTarget* target); + /** Fill out these strings for the given target. Libraries to link, * flags, and linkflags. */ void GetTargetFlags(std::string& linkLibs, @@ -430,8 +446,6 @@ protected: bool IgnoreLibPrefix; bool Configured; bool EmitUniversalBinaryFlags; - // A type flag is not nice. It's used only in TraceDependencies(). - bool IsMakefileGenerator; // Hack for ExpandRuleVariable until object-oriented version is // committed. std::string TargetImplib; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index d902f4ef7..a522e37e2 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -27,7 +27,6 @@ cmLocalNinjaGenerator::cmLocalNinjaGenerator() , ConfigName("") , HomeRelativeOutputPath("") { - this->IsMakefileGenerator = true; #ifdef _WIN32 this->WindowsShell = true; #endif @@ -302,7 +301,12 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc, wd = this->GetMakefile()->GetStartOutputDirectory(); cmOStringStream cdCmd; - cdCmd << "cd " << this->ConvertToOutputFormat(wd, SHELL); +#ifdef _WIN32 + std::string cdStr = "cd /D "; +#else + std::string cdStr = "cd "; +#endif + cdCmd << cdStr << this->ConvertToOutputFormat(wd, SHELL); cmdLines.push_back(cdCmd.str()); } for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) { @@ -335,14 +339,15 @@ cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( this->AppendCustomCommandLines(cc, cmdLines); if (cmdLines.empty()) { - cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(), - "Phony custom command for " + - ninjaOutputs[0], - ninjaOutputs, - ninjaDeps, - cmNinjaDeps(), - orderOnlyDeps, - cmNinjaVars()); + this->GetGlobalNinjaGenerator()->WritePhonyBuild( + this->GetBuildFileStream(), + "Phony custom command for " + + ninjaOutputs[0], + ninjaOutputs, + ninjaDeps, + cmNinjaDeps(), + orderOnlyDeps, + cmNinjaVars()); } else { this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild( this->BuildCommandLine(cmdLines), diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 0f680f6a1..56da1f936 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -92,7 +92,6 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3() this->SkipPreprocessedSourceRules = false; this->SkipAssemblySourceRules = false; this->MakeCommandEscapeTargetTwice = false; - this->IsMakefileGenerator = true; this->BorlandMakeCurlyHack = false; } @@ -1304,7 +1303,7 @@ cmLocalUnixMakefileGenerator3 std::string unmodified = s; unmodified += s2; // if there is no restriction on the length of make variables - // and there are no "." charactors in the string, then return the + // and there are no "." characters in the string, then return the // unmodified combination. if((!this->MakefileVariableSize && unmodified.find('.') == s.npos) && (!this->MakefileVariableSize && unmodified.find('+') == s.npos) @@ -1345,7 +1344,7 @@ cmLocalUnixMakefileGenerator3 return ret; } - // if the string is greater the 32 chars it is an invalid vairable name + // if the string is greater than 32 chars it is an invalid variable name // for borland make if(static_cast<int>(ret.size()) > this->MakefileVariableSize) { @@ -1353,8 +1352,8 @@ cmLocalUnixMakefileGenerator3 int size = keep + 3; std::string str1 = s; std::string str2 = s2; - // we must shorten the combined string by 4 charactors - // keep no more than 24 charactors from the second string + // we must shorten the combined string by 4 characters + // keep no more than 24 characters from the second string if(static_cast<int>(str2.size()) > keep) { str2 = str2.substr(0, keep); @@ -1962,8 +1961,8 @@ void cmLocalUnixMakefileGenerator3 // Build a list of preprocessor definitions for the target. std::set<std::string> defines; - this->AppendDefines(defines, target.GetCompileDefinitions( - this->ConfigurationName.c_str())); + this->AddCompileDefinitions(defines, &target, + this->ConfigurationName.c_str()); if(!defines.empty()) { cmakefileStream diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index dc94476c8..e5b4057d2 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -573,22 +573,20 @@ cmLocalVisualStudio6Generator // Add the rule with the given dependencies and commands. const char* no_main_dependency = 0; - this->Makefile->AddCustomCommandToOutput(output, - depends, - no_main_dependency, - origCommand.GetCommandLines(), - comment.c_str(), - origCommand.GetWorkingDirectory()); + if(cmSourceFile* outsf = + this->Makefile->AddCustomCommandToOutput( + output, depends, no_main_dependency, + origCommand.GetCommandLines(), comment.c_str(), + origCommand.GetWorkingDirectory())) + { + target.AddSourceFile(outsf); + } // Replace the dependencies with the output of this rule so that the // next rule added will run after this one. depends.clear(); depends.push_back(output); - // Add a source file representing this output to the project. - cmSourceFile* outsf = this->Makefile->GetSourceFileWithOutput(output); - target.AddSourceFile(outsf); - // Free the fake output name. delete [] output; } @@ -1171,18 +1169,42 @@ void cmLocalVisualStudio6Generator std::string extraLinkOptionsRelWithDebInfo; if(target.GetType() == cmTarget::EXECUTABLE) { - extraLinkOptions = - this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS"); + extraLinkOptions = this->Makefile-> + GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS"); + extraLinkOptionsDebug = this->Makefile-> + GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_DEBUG"); + extraLinkOptionsRelease = this->Makefile-> + GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_RELEASE"); + extraLinkOptionsMinSizeRel = this->Makefile-> + GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_MINSIZEREL"); + extraLinkOptionsRelWithDebInfo = this->Makefile-> + GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO"); } if(target.GetType() == cmTarget::SHARED_LIBRARY) { - extraLinkOptions = - this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS"); + extraLinkOptions = this->Makefile-> + GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS"); + extraLinkOptionsDebug = this->Makefile-> + GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_DEBUG"); + extraLinkOptionsRelease = this->Makefile-> + GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_RELEASE"); + extraLinkOptionsMinSizeRel = this->Makefile-> + GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL"); + extraLinkOptionsRelWithDebInfo = this->Makefile-> + GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO"); } if(target.GetType() == cmTarget::MODULE_LIBRARY) { - extraLinkOptions = - this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS"); + extraLinkOptions = this->Makefile-> + GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS"); + extraLinkOptionsDebug = this->Makefile-> + GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_DEBUG"); + extraLinkOptionsRelease = this->Makefile-> + GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_RELEASE"); + extraLinkOptionsMinSizeRel = this->Makefile-> + GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL"); + extraLinkOptionsRelWithDebInfo = this->Makefile-> + GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO"); } // Get extra linker options for this target. @@ -1228,7 +1250,7 @@ void cmLocalVisualStudio6Generator if(!linkLanguage) { cmSystemTools::Error - ("CMake can not determine linker language for target:", + ("CMake can not determine linker language for target: ", target.GetName()); return; } @@ -1435,38 +1457,39 @@ void cmLocalVisualStudio6Generator std::string staticLibOptionsRelWithDebInfo; if(target.GetType() == cmTarget::STATIC_LIBRARY ) { - if(const char* libflags = target.GetProperty("STATIC_LIBRARY_FLAGS")) - { - staticLibOptions = libflags; - staticLibOptionsDebug = libflags; - staticLibOptionsRelease = libflags; - staticLibOptionsMinSizeRel = libflags; - staticLibOptionsRelWithDebInfo = libflags; - } - if(const char* libflagsDebug = - target.GetProperty("STATIC_LIBRARY_FLAGS_DEBUG")) - { - staticLibOptionsDebug += " "; - staticLibOptionsDebug = libflagsDebug; - } - if(const char* libflagsRelease = - target.GetProperty("STATIC_LIBRARY_FLAGS_RELEASE")) - { - staticLibOptionsRelease += " "; - staticLibOptionsRelease = libflagsRelease; - } - if(const char* libflagsMinSizeRel = - target.GetProperty("STATIC_LIBRARY_FLAGS_MINSIZEREL")) - { - staticLibOptionsMinSizeRel += " "; - staticLibOptionsMinSizeRel = libflagsMinSizeRel; - } - if(const char* libflagsRelWithDebInfo = - target.GetProperty("STATIC_LIBRARY_FLAGS_RELWITHDEBINFO")) - { - staticLibOptionsRelWithDebInfo += " "; - staticLibOptionsRelWithDebInfo = libflagsRelWithDebInfo; - } + const char *libflagsGlobal = + this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS"); + this->AppendFlags(staticLibOptions, libflagsGlobal); + this->AppendFlags(staticLibOptionsDebug, libflagsGlobal); + this->AppendFlags(staticLibOptionsRelease, libflagsGlobal); + this->AppendFlags(staticLibOptionsMinSizeRel, libflagsGlobal); + this->AppendFlags(staticLibOptionsRelWithDebInfo, libflagsGlobal); + + this->AppendFlags(staticLibOptionsDebug, this->Makefile-> + GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_DEBUG")); + this->AppendFlags(staticLibOptionsRelease, this->Makefile-> + GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_RELEASE")); + this->AppendFlags(staticLibOptionsMinSizeRel, this->Makefile-> + GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL")); + this->AppendFlags(staticLibOptionsRelWithDebInfo, this->Makefile-> + GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO")); + + const char *libflags = target.GetProperty("STATIC_LIBRARY_FLAGS"); + this->AppendFlags(staticLibOptions, libflags); + this->AppendFlags(staticLibOptionsDebug, libflags); + this->AppendFlags(staticLibOptionsRelease, libflags); + this->AppendFlags(staticLibOptionsMinSizeRel, libflags); + this->AppendFlags(staticLibOptionsRelWithDebInfo, libflags); + + this->AppendFlags(staticLibOptionsDebug, + target.GetProperty("STATIC_LIBRARY_FLAGS_DEBUG")); + this->AppendFlags(staticLibOptionsRelease, + target.GetProperty("STATIC_LIBRARY_FLAGS_RELEASE")); + this->AppendFlags(staticLibOptionsMinSizeRel, + target.GetProperty("STATIC_LIBRARY_FLAGS_MINSIZEREL")); + this->AppendFlags(staticLibOptionsRelWithDebInfo, + target.GetProperty("STATIC_LIBRARY_FLAGS_RELWITHDEBINFO")); + std::string objects; this->OutputObjects(target, "LIB", objects); if(!objects.empty()) @@ -1639,9 +1662,9 @@ void cmLocalVisualStudio6Generator // store flags for each configuration std::string flags = " "; std::string flagsRelease = " "; - std::string flagsMinSize = " "; + std::string flagsMinSizeRel = " "; std::string flagsDebug = " "; - std::string flagsDebugRel = " "; + std::string flagsRelWithDebInfo = " "; if(target.GetType() >= cmTarget::EXECUTABLE && target.GetType() <= cmTarget::OBJECT_LIBRARY) { @@ -1649,7 +1672,7 @@ void cmLocalVisualStudio6Generator if(!linkLanguage) { cmSystemTools::Error - ("CMake can not determine linker language for target:", + ("CMake can not determine linker language for target: ", target.GetName()); return; } @@ -1664,16 +1687,24 @@ void cmLocalVisualStudio6Generator flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" "; flagVar = baseFlagVar + "_MINSIZEREL"; - flagsMinSize = this->Makefile->GetSafeDefinition(flagVar.c_str()); - flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" "; + flagsMinSizeRel = this->Makefile->GetSafeDefinition(flagVar.c_str()); + flagsMinSizeRel += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" "; flagVar = baseFlagVar + "_DEBUG"; flagsDebug = this->Makefile->GetSafeDefinition(flagVar.c_str()); flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" "; flagVar = baseFlagVar + "_RELWITHDEBINFO"; - flagsDebugRel = this->Makefile->GetSafeDefinition(flagVar.c_str()); - flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" "; + flagsRelWithDebInfo = this->Makefile->GetSafeDefinition(flagVar.c_str()); + flagsRelWithDebInfo += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" "; + + this->AddCompileOptions(flags, &target, linkLanguage, 0); + this->AddCompileOptions(flagsDebug, &target, linkLanguage, "Debug"); + this->AddCompileOptions(flagsRelease, &target, linkLanguage, "Release"); + this->AddCompileOptions(flagsMinSizeRel, &target, linkLanguage, + "MinSizeRel"); + this->AddCompileOptions(flagsRelWithDebInfo, &target, linkLanguage, + "RelWithDebInfo"); } // if _UNICODE and _SBCS are not found, then add -D_MBCS @@ -1686,13 +1717,6 @@ void cmLocalVisualStudio6Generator flags += " /D \"_MBCS\""; } - // Add per-target flags. - if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS")) - { - flags += " "; - flags += targetFlags; - } - // Add per-target and per-configuration preprocessor definitions. std::set<std::string> definesSet; std::set<std::string> debugDefinesSet; @@ -1700,21 +1724,11 @@ void cmLocalVisualStudio6Generator std::set<std::string> minsizeDefinesSet; std::set<std::string> debugrelDefinesSet; - this->AppendDefines( - definesSet, - target.GetCompileDefinitions(0)); - this->AppendDefines( - debugDefinesSet, - target.GetCompileDefinitions("DEBUG")); - this->AppendDefines( - releaseDefinesSet, - target.GetCompileDefinitions("RELEASE")); - this->AppendDefines( - minsizeDefinesSet, - target.GetCompileDefinitions("MINSIZEREL")); - this->AppendDefines( - debugrelDefinesSet, - target.GetCompileDefinitions("RELWITHDEBINFO")); + this->AddCompileDefinitions(definesSet, &target, 0); + this->AddCompileDefinitions(debugDefinesSet, &target, "DEBUG"); + this->AddCompileDefinitions(releaseDefinesSet, &target, "RELEASE"); + this->AddCompileDefinitions(minsizeDefinesSet, &target, "MINSIZEREL"); + this->AddCompileDefinitions(debugrelDefinesSet, &target, "RELWITHDEBINFO"); std::string defines = " "; std::string debugDefines = " "; @@ -1731,19 +1745,19 @@ void cmLocalVisualStudio6Generator flags += defines; flagsDebug += debugDefines; flagsRelease += releaseDefines; - flagsMinSize += minsizeDefines; - flagsDebugRel += debugrelDefines; + flagsMinSizeRel += minsizeDefines; + flagsRelWithDebInfo += debugrelDefines; // The template files have CXX FLAGS in them, that need to be replaced. // There are not separate CXX and C template files, so we use the same // variable names. The previous code sets up flags* variables to contain // the correct C or CXX flags cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL", - flagsMinSize.c_str()); + flagsMinSizeRel.c_str()); cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG", flagsDebug.c_str()); cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO", - flagsDebugRel.c_str()); + flagsRelWithDebInfo.c_str()); cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE", flagsRelease.c_str()); cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str()); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 7d0bc67ed..8ffd96eb1 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -146,11 +146,10 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() force += "/"; force += tgt.GetName(); force += "_force"; - this->Makefile->AddCustomCommandToOutput(force.c_str(), no_depends, - no_main_dependency, - force_commands, " ", 0, true); if(cmSourceFile* file = - this->Makefile->GetSourceFileWithOutput(force.c_str())) + this->Makefile->AddCustomCommandToOutput( + force.c_str(), no_depends, no_main_dependency, + force_commands, " ", 0, true)) { tgt.AddSourceFile(file); } @@ -202,7 +201,7 @@ void cmLocalVisualStudio7Generator::WriteStampFiles() stampName += "/"; stampName += "generate.stamp"; std::ofstream stamp(stampName.c_str()); - stamp << "# CMake generation timestamp file this directory.\n"; + stamp << "# CMake generation timestamp file for this directory.\n"; // Create a helper file so CMake can determine when it is run // through the rule created by CreateVCProjBuildRule whether it @@ -443,12 +442,12 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] = {"InlineFunctionExpansion", "Ob0", "no inlines", "0", 0}, {"InlineFunctionExpansion", "Ob1", "when inline keyword", "1", 0}, {"InlineFunctionExpansion", "Ob2", "any time you can inline", "2", 0}, - {"RuntimeLibrary", "MTd", "Multithreded debug", "1", 0}, - {"RuntimeLibrary", "MT", "Multithreded", "0", 0}, - {"RuntimeLibrary", "MDd", "Multithreded dll debug", "3", 0}, - {"RuntimeLibrary", "MD", "Multithreded dll", "2", 0}, - {"RuntimeLibrary", "MLd", "Sinble Thread debug", "5", 0}, - {"RuntimeLibrary", "ML", "Sinble Thread", "4", 0}, + {"RuntimeLibrary", "MTd", "Multithreaded debug", "1", 0}, + {"RuntimeLibrary", "MT", "Multithreaded", "0", 0}, + {"RuntimeLibrary", "MDd", "Multithreaded dll debug", "3", 0}, + {"RuntimeLibrary", "MD", "Multithreaded dll", "2", 0}, + {"RuntimeLibrary", "MLd", "Single Thread debug", "5", 0}, + {"RuntimeLibrary", "ML", "Single Thread", "4", 0}, {"StructMemberAlignment", "Zp16", "struct align 16 byte ", "5", 0}, {"StructMemberAlignment", "Zp1", "struct align 1 byte ", "1", 0}, {"StructMemberAlignment", "Zp2", "struct align 2 byte ", "2", 0}, @@ -476,6 +475,11 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] = {"ForcedIncludeFiles", "FI", "Forced include files", "", cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SemicolonAppendable}, + {"AssemblerListingLocation", "Fa", "ASM List Location", "", + cmVS7FlagTable::UserValue}, + {"ProgramDataBaseFileName", "Fd", "Program Database File Name", "", + cmVS7FlagTable::UserValue}, + // boolean flags {"BufferSecurityCheck", "GS", "Buffer security check", "TRUE", 0}, {"BufferSecurityCheck", "GS-", "Turn off Buffer security check", "FALSE", 0}, @@ -683,7 +687,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, if(!linkLanguage) { cmSystemTools::Error - ("CMake can not determine linker language for target:", + ("CMake can not determine linker language for target: ", target.GetName()); return; } @@ -708,6 +712,9 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, { flags += " /TP "; } + + // Add the target-specific flags. + this->AddCompileOptions(flags, &target, linkLanguage, configName); } if(this->FortranProject) @@ -720,13 +727,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, } } - // Add the target-specific flags. - if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS")) - { - flags += " "; - flags += targetFlags; - } - // Get preprocessor definitions for this directory. std::string defineFlags = this->Makefile->GetDefineFlags(); Options::Tool t = Options::Compiler; @@ -740,12 +740,16 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, table, this->ExtraFlagTable); targetOptions.FixExceptionHandlingDefault(); + std::string asmLocation = std::string(configName) + "/"; + targetOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str()); targetOptions.Parse(flags.c_str()); targetOptions.Parse(defineFlags.c_str()); targetOptions.ParseFinish(); cmGeneratorTarget* gt = this->GlobalGenerator->GetGeneratorTarget(&target); - targetOptions.AddDefines(target.GetCompileDefinitions(configName).c_str()); + std::vector<std::string> targetDefines; + target.GetCompileDefinitions(targetDefines, configName); + targetOptions.AddDefines(targetDefines); targetOptions.SetVerboseMakefile( this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); @@ -836,18 +840,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, fout << "\"\n"; targetOptions.OutputFlagMap(fout, "\t\t\t\t"); targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX"); - fout << "\t\t\t\tAssemblerListingLocation=\"" << configName << "\"\n"; fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n"; - if(targetBuilds) - { - // We need to specify a program database file name even for - // non-debug configurations because VS still creates .idb files. - fout << "\t\t\t\tProgramDataBaseFileName=\"" - << this->ConvertToXMLOutputPathSingle( - target.GetPDBDirectory(configName).c_str()) - << "/" - << target.GetPDBName(configName) << "\"\n"; - } fout << "/>\n"; // end of <Tool Name=VCCLCompilerTool tool = "VCCustomBuildTool"; if(this->FortranProject) @@ -928,7 +921,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, } this->OutputTargetRules(fout, configName, target, libName); - this->OutputBuildTool(fout, configName, target, targetOptions.IsDebug()); + this->OutputBuildTool(fout, configName, target, targetOptions); fout << "\t\t</Configuration>\n"; } @@ -949,9 +942,7 @@ cmLocalVisualStudio7Generator } void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, - const char* configName, - cmTarget &target, - bool isDebug) + const char* configName, cmTarget &target, const Options& targetOptions) { cmGlobalVisualStudio7Generator* gg = static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator); @@ -1047,17 +1038,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, } } std::string libflags; - if(const char* flags = target.GetProperty("STATIC_LIBRARY_FLAGS")) - { - libflags += flags; - } - std::string libFlagsConfig = "STATIC_LIBRARY_FLAGS_"; - libFlagsConfig += configTypeUpper; - if(const char* flagsConfig = target.GetProperty(libFlagsConfig.c_str())) - { - libflags += " "; - libflags += flagsConfig; - } + this->GetStaticLibraryFlags(libflags, configTypeUpper, &target); if(!libflags.empty()) { fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n"; @@ -1129,7 +1110,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, temp += targetNamePDB; fout << "\t\t\t\tProgramDatabaseFile=\"" << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n"; - if(isDebug) + if(targetOptions.IsDebug()) { fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n"; } @@ -1227,7 +1208,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, fout << "\t\t\t\tProgramDatabaseFile=\"" << path << "/" << targetNamePDB << "\"\n"; - if(isDebug) + if(targetOptions.IsDebug()) { fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n"; } @@ -1241,9 +1222,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, { fout << "\t\t\t\tSubSystem=\"8\"\n"; } - fout << "\t\t\t\tEntryPointSymbol=\"" - << (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup") - << "\"\n"; + + if(!linkOptions.GetFlag("EntryPointSymbol")) + { + const char* entryPointSymbol = targetOptions.UsingUnicode() ? + (isWin32Executable ? "wWinMainCRTStartup" : "mainWCRTStartup") : + (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup"); + fout << "\t\t\t\tEntryPointSymbol=\"" << entryPointSymbol << "\"\n"; + } } else if ( this->FortranProject ) { @@ -1970,23 +1956,27 @@ cmLocalVisualStudio7Generator // Compute the version of the Intel plugin to the VS IDE. // If the key does not exist then use a default guess. - std::string intelVersion = "9.10"; + std::string intelVersion; std::string vskey = gg->GetRegistryBase(); vskey += "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion"; cmSystemTools::ReadRegistryValue(vskey.c_str(), intelVersion, cmSystemTools::KeyWOW64_32); - if (intelVersion.find("13") == 0 || - intelVersion.find("12") == 0 || - intelVersion.find("11") == 0) + unsigned int intelVersionNumber = ~0u; + sscanf(intelVersion.c_str(), "%u", &intelVersionNumber); + if(intelVersionNumber >= 11) { - // Version 11.x, 12.x, and 13.x actually use 11.0 in project files! - intelVersion = "11.0" ; + // Default to latest known project file version. + intelVersion = "11.0"; } - else if(intelVersion.find("10") == 0) + else if(intelVersionNumber == 10) { // Version 10.x actually uses 9.10 in project files! intelVersion = "9.10"; } + else + { + // Version <= 9: use ProductVersion from registry. + } fout << "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n" << "<VisualStudioProject\n" diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index d9e2ef0dd..92e4d3c12 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -90,7 +90,7 @@ private: void OutputTargetRules(std::ostream& fout, const char* configName, cmTarget &target, const char *libName); void OutputBuildTool(std::ostream& fout, const char* configName, - cmTarget& t, bool debug); + cmTarget& t, const Options& targetOptions); void OutputLibraryDirectories(std::ostream& fout, std::vector<std::string> const& dirs); void WriteProjectSCC(std::ostream& fout, cmTarget& target); diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index 551ebd30a..7c5f69df5 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -33,3 +33,12 @@ cmLocalXCodeGenerator::GetTargetDirectory(cmTarget const&) const // No per-target directory for this generator (yet). return ""; } + +//---------------------------------------------------------------------------- +void cmLocalXCodeGenerator::AppendFlagEscape(std::string& flags, + const char* rawFlag) +{ + cmGlobalXCodeGenerator* gg = + static_cast<cmGlobalXCodeGenerator*>(this->GlobalGenerator); + gg->AppendFlag(flags, rawFlag); +} diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h index eab228f6b..d97a41cea 100644 --- a/Source/cmLocalXCodeGenerator.h +++ b/Source/cmLocalXCodeGenerator.h @@ -28,6 +28,7 @@ public: virtual ~cmLocalXCodeGenerator(); virtual std::string GetTargetDirectory(cmTarget const& target) const; + virtual void AppendFlagEscape(std::string& flags, const char* rawFlag); private: }; diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index bd7ec004b..8ba612cc9 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -227,7 +227,7 @@ bool cmMacroHelperCommand::InvokeInitialPass } arg.Value = tmps; - arg.Quoted = k->Quoted; + arg.Delim = k->Delim; arg.FilePath = k->FilePath; arg.Line = k->Line; newLFF.Arguments.push_back(arg); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 47a6d2e66..34541e996 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -21,6 +21,7 @@ #include "cmCacheManager.h" #include "cmFunctionBlocker.h" #include "cmListFileCache.h" +#include "cmDocumentGeneratorExpressions.h" #include "cmCommandArgumentParserHelper.h" #include "cmDocumentCompileDefinitions.h" #include "cmGeneratorExpression.h" @@ -40,6 +41,7 @@ #include <stack> #include <ctype.h> // for isspace +#include <assert.h> class cmMakefile::Internals { @@ -148,6 +150,7 @@ cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals) this->Initialize(); this->CheckSystemVars = mf.CheckSystemVars; this->ListFileStack = mf.ListFileStack; + this->OutputToSource = mf.OutputToSource; } //---------------------------------------------------------------------------- @@ -813,6 +816,19 @@ bool cmMakefile::NeedBackwardsCompatibility(unsigned int major, } } + +namespace +{ + struct file_not_persistent + { + bool operator()(const std::string& path) const + { + return !(path.find("CMakeTmp") == path.npos && + cmSystemTools::FileExists(path.c_str())); + } + }; +} + void cmMakefile::FinalPass() { // do all the variable expansions here @@ -826,6 +842,29 @@ void cmMakefile::FinalPass() (*i)->FinalPass(); } + //go through all configured files and see which ones still exist. + //we don't want cmake to re-run if a configured file is created and deleted + //during processing as that would make it a transient file that can't + //influence the build process + + //remove_if will move all items that don't have a valid file name to the + //back of the vector + std::vector<std::string>::iterator new_output_files_end = std::remove_if( + this->OutputFiles.begin(), + this->OutputFiles.end(), + file_not_persistent() ); + //we just have to erase all items at the back + this->OutputFiles.erase(new_output_files_end, this->OutputFiles.end() ); + + //if a configured file is used as input for another configured file, + //and then deleted it will show up in the input list files so we + //need to scan those too + std::vector<std::string>::iterator new_list_files_end = std::remove_if( + this->ListFiles.begin(), + this->ListFiles.end(), + file_not_persistent() ); + + this->ListFiles.erase(new_list_files_end, this->ListFiles.end() ); } // Generate the output file @@ -1008,11 +1047,45 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs, cc->SetEscapeOldStyle(escapeOldStyle); cc->SetEscapeAllowMakeVars(true); file->SetCustomCommand(cc); + this->UpdateOutputToSourceMap(outputs, file); } return file; } //---------------------------------------------------------------------------- +void +cmMakefile::UpdateOutputToSourceMap(std::vector<std::string> const& outputs, + cmSourceFile* source) +{ + for(std::vector<std::string>::const_iterator o = outputs.begin(); + o != outputs.end(); ++o) + { + this->UpdateOutputToSourceMap(*o, source); + } +} + +//---------------------------------------------------------------------------- +void +cmMakefile::UpdateOutputToSourceMap(std::string const& output, + cmSourceFile* source) +{ + OutputToSourceMap::iterator i = this->OutputToSource.find(output); + if(i != this->OutputToSource.end()) + { + // Multiple custom commands produce the same output but may + // be attached to a different source file (MAIN_DEPENDENCY). + // LinearGetSourceFileWithOutput would return the first one, + // so keep the mapping for the first one. + // + // TODO: Warn the user about this case. However, the VS 8 generator + // triggers it for separate generate.stamp rules in ZERO_CHECK and + // individual targets. + return; + } + this->OutputToSource[output] = source; +} + +//---------------------------------------------------------------------------- cmSourceFile* cmMakefile::AddCustomCommandToOutput(const char* output, const std::vector<std::string>& depends, @@ -1270,6 +1343,11 @@ void cmMakefile::RemoveDefineFlag(const char* flag, } } +void cmMakefile::AddCompileOption(const char* option) +{ + this->AppendProperty("COMPILE_OPTIONS", option); +} + bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) { // Create a regular expression to match valid definitions. @@ -1431,12 +1509,20 @@ void cmMakefile::AddLinkDirectoryForTarget(const char *target, cmTargets::iterator i = this->Targets.find(target); if ( i != this->Targets.end()) { + if(this->IsAlias(target)) + { + cmOStringStream e; + e << "ALIAS target \"" << target << "\" " + << "may not be linked into another target."; + this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } i->second.AddLinkDirectory( d ); } else { cmSystemTools::Error - ("Attempt to add link directories to non-existant target: ", + ("Attempt to add link directories to non-existent target: ", target, " for directory ", d); } } @@ -1493,6 +1579,18 @@ void cmMakefile::InitializeFromParent() parentIncludes.begin(), parentIncludes.end()); + const std::vector<cmValueWithOrigin> parentOptions = + parent->GetCompileOptionsEntries(); + this->CompileOptionsEntries.insert(this->CompileOptionsEntries.end(), + parentOptions.begin(), + parentOptions.end()); + + const std::vector<cmValueWithOrigin> parentDefines = + parent->GetCompileDefinitionsEntries(); + this->CompileDefinitionsEntries.insert(this->CompileDefinitionsEntries.end(), + parentDefines.begin(), + parentDefines.end()); + this->SystemIncludeDirectories = parent->SystemIncludeDirectories; // define flags @@ -1663,27 +1761,13 @@ cmMakefile::AddSystemIncludeDirectories(const std::set<cmStdString> &incs) { this->SystemIncludeDirectories.insert(*li); } -} -//---------------------------------------------------------------------------- -bool cmMakefile::IsSystemIncludeDirectory(const char* dir, const char *config) -{ - for (std::set<cmStdString>::const_iterator - it = this->SystemIncludeDirectories.begin(); - it != this->SystemIncludeDirectories.end(); ++it) + for (cmTargets::iterator l = this->Targets.begin(); + l != this->Targets.end(); ++l) { - cmListFileBacktrace lfbt; - cmGeneratorExpression ge(lfbt); - - std::vector<std::string> incs; - cmSystemTools::ExpandListArgument(ge.Parse(*it) - ->Evaluate(this, config, false), incs); - if (std::find(incs.begin(), incs.end(), dir) != incs.end()) - { - return true; - } + cmTarget &t = l->second; + t.AddSystemIncludeDirectories(incs); } - return false; } void cmMakefile::AddDefinition(const char* name, const char* value) @@ -1919,6 +2003,12 @@ void cmMakefile::AddGlobalLinkInformation(const char* name, cmTarget& target) } +void cmMakefile::AddAlias(const char* lname, cmTarget *tgt) +{ + this->AliasTargets[lname] = tgt; + this->LocalGenerator->GetGlobalGenerator()->AddAlias(lname, tgt); +} + cmTarget* cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type, const std::vector<std::string> &srcs, bool excludeFromAll) @@ -1975,7 +2065,7 @@ cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name) return &it->second; } -cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname) +cmSourceFile *cmMakefile::LinearGetSourceFileWithOutput(const char *cname) { std::string name = cname; std::string out; @@ -2011,6 +2101,25 @@ cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname) return 0; } +cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname) +{ + std::string name = cname; + + // If the queried path is not absolute we use the backward compatible + // linear-time search for an output with a matching suffix. + if(!cmSystemTools::FileIsFullPath(cname)) + { + return LinearGetSourceFileWithOutput(cname); + } + // Otherwise we use an efficient lookup map. + OutputToSourceMap::iterator o = this->OutputToSource.find(name); + if (o != this->OutputToSource.end()) + { + return (*o).second; + } + return 0; +} + #if defined(CMAKE_BUILD_WITH_CMAKE) cmSourceGroup* cmMakefile::GetSourceGroup(const std::vector<std::string>&name) { @@ -2086,7 +2195,7 @@ void cmMakefile::AddSourceGroup(const std::vector<std::string>& name, } else if(i==-1) { - // group does not exists nor belong to any existing group + // group does not exist nor belong to any existing group // add its first component this->SourceGroups.push_back(cmSourceGroup(name[0].c_str(), regex)); sg = this->GetSourceGroup(currentName); @@ -2780,7 +2889,7 @@ bool cmMakefile::ExpandArguments( // If the argument is quoted, it should be one argument. // Otherwise, it may be a list of arguments. - if(i->Quoted) + if(i->Delim == cmListFileArgument::Quoted) { outArgs.push_back(value); } @@ -3357,8 +3466,14 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile, } std::string soutfile = outfile; std::string sinfile = infile; - this->AddCMakeDependFile(infile); + this->AddCMakeDependFile(sinfile); cmSystemTools::ConvertToUnixSlashes(soutfile); + + // Re-generate if non-temporary outputs are missing. + //when we finalize the configuration we will remove all + //output files that now don't exist. + this->AddCMakeOutputFile(soutfile); + mode_t perm = 0; cmSystemTools::GetPermissions(sinfile.c_str(), perm); std::string::size_type pos = soutfile.rfind('/'); @@ -3468,6 +3583,31 @@ void cmMakefile::SetProperty(const char* prop, const char* value) cmValueWithOrigin(value, lfbt)); return; } + if (propname == "COMPILE_OPTIONS") + { + this->CompileOptionsEntries.clear(); + if (!value) + { + return; + } + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + this->CompileOptionsEntries.push_back(cmValueWithOrigin(value, lfbt)); + return; + } + if (propname == "COMPILE_DEFINITIONS") + { + this->CompileDefinitionsEntries.clear(); + if (!value) + { + return; + } + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + cmValueWithOrigin entry(value, lfbt); + this->CompileDefinitionsEntries.push_back(entry); + return; + } if ( propname == "INCLUDE_REGULAR_EXPRESSION" ) { @@ -3507,6 +3647,22 @@ void cmMakefile::AppendProperty(const char* prop, const char* value, cmValueWithOrigin(value, lfbt)); return; } + if (propname == "COMPILE_OPTIONS") + { + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + this->CompileOptionsEntries.push_back( + cmValueWithOrigin(value, lfbt)); + return; + } + if (propname == "COMPILE_DEFINITIONS") + { + cmListFileBacktrace lfbt; + this->GetBacktrace(lfbt); + this->CompileDefinitionsEntries.push_back( + cmValueWithOrigin(value, lfbt)); + return; + } if ( propname == "LINK_DIRECTORIES" ) { std::vector<std::string> varArgsExpanded; @@ -3632,6 +3788,34 @@ const char *cmMakefile::GetProperty(const char* prop, } return output.c_str(); } + else if (!strcmp("COMPILE_OPTIONS",prop)) + { + std::string sep; + for (std::vector<cmValueWithOrigin>::const_iterator + it = this->CompileOptionsEntries.begin(), + end = this->CompileOptionsEntries.end(); + it != end; ++it) + { + output += sep; + output += it->Value; + sep = ";"; + } + return output.c_str(); + } + else if (!strcmp("COMPILE_DEFINITIONS",prop)) + { + std::string sep; + for (std::vector<cmValueWithOrigin>::const_iterator + it = this->CompileDefinitionsEntries.begin(), + end = this->CompileDefinitionsEntries.end(); + it != end; ++it) + { + output += sep; + output += it->Value; + sep = ";"; + } + return output.c_str(); + } bool chain = false; const char *retVal = @@ -3680,8 +3864,17 @@ const char* cmMakefile::GetFeature(const char* feature, const char* config) return 0; } -cmTarget* cmMakefile::FindTarget(const char* name) +cmTarget* cmMakefile::FindTarget(const char* name, bool excludeAliases) { + if (!excludeAliases) + { + std::map<std::string, cmTarget*>::iterator i + = this->AliasTargets.find(name); + if (i != this->AliasTargets.end()) + { + return i->second; + } + } cmTargets& tgts = this->GetTargets(); cmTargets::iterator i = tgts.find ( name ); @@ -3986,23 +4179,36 @@ void cmMakefile::DefineProperties(cmake *cm) ("INCLUDE_DIRECTORIES", cmProperty::DIRECTORY, "List of preprocessor include file search directories.", "This property specifies the list of directories given " - "so far to the include_directories command. " - "This property exists on directories and targets. " + "so far to the include_directories command. " + "This property exists on directories and targets. " "In addition to accepting values from the include_directories " "command, values may be set directly on any directory or any " - "target using the set_property command. " + "target using the set_property command. " "A target gets its initial value for this property from the value " - "of the directory property. " + "of the directory property. " "A directory gets its initial value from its parent directory if " - "it has one. " + "it has one. " "Both directory and target property values are adjusted by calls " "to the include_directories command." "\n" "The target property values are used by the generators to set " - "the include paths for the compiler. " + "the include paths for the compiler. " "See also the include_directories command."); cm->DefineProperty + ("COMPILE_OPTIONS", cmProperty::DIRECTORY, + "List of options to pass to the compiler.", + "This property specifies the list of directories given " + "so far for this property. " + "This property exists on directories and targets." + "\n" + "The target property values are used by the generators to set " + "the options for the compiler.\n" + "Contents of COMPILE_OPTIONS may use \"generator expressions\" with " + "the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + + cm->DefineProperty ("LINK_DIRECTORIES", cmProperty::DIRECTORY, "List of linker search directories.", "This read-only property specifies the list of directories given " @@ -4043,7 +4249,7 @@ void cmMakefile::DefineProperties(cmake *cm) "\n" "This property only works for Visual Studio 7 and above; it is ignored " "on other generators. The property only applies when set on a directory " - "whose CMakeLists.txt conatins a project() command."); + "whose CMakeLists.txt contains a project() command."); cm->DefineProperty ("VS_GLOBAL_SECTION_POST_<section>", cmProperty::DIRECTORY, "Specify a postSolution global section in Visual Studio.", @@ -4059,7 +4265,7 @@ void cmMakefile::DefineProperties(cmake *cm) "\n" "This property only works for Visual Studio 7 and above; it is ignored " "on other generators. The property only applies when set on a directory " - "whose CMakeLists.txt conatins a project() command." + "whose CMakeLists.txt contains a project() command." "\n" "Note that CMake generates postSolution sections ExtensibilityGlobals " "and ExtensibilityAddIns by default. If you set the corresponding " @@ -4093,7 +4299,7 @@ cmMakefile::AddImportedTarget(const char* name, cmTarget::TargetType type, } //---------------------------------------------------------------------------- -cmTarget* cmMakefile::FindTargetToUse(const char* name) +cmTarget* cmMakefile::FindTargetToUse(const char* name, bool excludeAliases) { // Look for an imported target. These take priority because they // are more local in scope and do not have to be globally unique. @@ -4105,15 +4311,25 @@ cmTarget* cmMakefile::FindTargetToUse(const char* name) } // Look for a target built in this directory. - if(cmTarget* t = this->FindTarget(name)) + if(cmTarget* t = this->FindTarget(name, excludeAliases)) { return t; } // Look for a target built in this project. - return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name); + return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name, + excludeAliases); } +//---------------------------------------------------------------------------- +bool cmMakefile::IsAlias(const char *name) +{ + if (this->AliasTargets.find(name) != this->AliasTargets.end()) + return true; + return this->GetLocalGenerator()->GetGlobalGenerator()->IsAlias(name); +} + +//---------------------------------------------------------------------------- cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name) { cmTarget *t = this->FindTargetToUse(name); @@ -4124,6 +4340,14 @@ cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name) bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg, bool isCustom) { + if(this->IsAlias(name.c_str())) + { + cmOStringStream e; + e << "cannot create target \"" << name + << "\" because an alias with the same name already exists."; + msg = e.str(); + return false; + } if(cmTarget* existing = this->FindTargetToUse(name.c_str())) { // The name given conflicts with an existing target. Produce an diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 74a731d5b..8bce9fd65 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -29,6 +29,9 @@ #include <cmsys/auto_ptr.hxx> #include <cmsys/RegularExpression.hxx> +#if defined(CMAKE_BUILD_WITH_CMAKE) +# include <cmsys/hash_map.hxx> +#endif class cmFunctionBlocker; class cmCommand; @@ -206,6 +209,7 @@ public: */ void AddDefineFlag(const char* definition); void RemoveDefineFlag(const char* definition); + void AddCompileOption(const char* option); /** Create a new imported target with the name and type given. */ cmTarget* AddImportedTarget(const char* name, cmTarget::TargetType type, @@ -336,6 +340,7 @@ public: cmTarget* AddLibrary(const char *libname, cmTarget::TargetType type, const std::vector<std::string> &srcs, bool excludeFromAll = false); + void AddAlias(const char *libname, cmTarget *tgt); #if defined(CMAKE_BUILD_WITH_CMAKE) /** @@ -535,11 +540,12 @@ public: this->GeneratorTargets = targets; } - cmTarget* FindTarget(const char* name); + cmTarget* FindTarget(const char* name, bool excludeAliases = false); /** Find a target to use in place of the given name. The target returned may be imported or built within the project. */ - cmTarget* FindTargetToUse(const char* name); + cmTarget* FindTargetToUse(const char* name, bool excludeAliases = false); + bool IsAlias(const char *name); cmGeneratorTarget* FindGeneratorTargetToUse(const char* name); /** @@ -647,7 +653,7 @@ public: const std::vector<std::string>& GetListFiles() const { return this->ListFiles; } ///! When the file changes cmake will be re-run from the build system. - void AddCMakeDependFile(const char* file) + void AddCMakeDependFile(const std::string& file) { this->ListFiles.push_back(file);} /** @@ -665,7 +671,7 @@ public: */ const std::vector<std::string>& GetOutputFiles() const { return this->OutputFiles; } - void AddCMakeOutputFile(const char* file) + void AddCMakeOutputFile(const std::string& file) { this->OutputFiles.push_back(file);} /** @@ -866,10 +872,21 @@ public: { return this->IncludeDirectoriesEntries; } + std::vector<cmValueWithOrigin> GetCompileOptionsEntries() const + { + return this->CompileOptionsEntries; + } + std::vector<cmValueWithOrigin> GetCompileDefinitionsEntries() const + { + return this->CompileDefinitionsEntries; + } bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; } void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; } + std::set<cmStdString> const & GetSystemIncludeDirectories() const + { return this->SystemIncludeDirectories; } + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(const char* name, cmTarget& target); @@ -890,6 +907,7 @@ protected: // libraries, classes, and executables cmTargets Targets; + std::map<std::string, cmTarget*> AliasTargets; cmGeneratorTargetsType GeneratorTargets; std::vector<cmSourceFile*> SourceFiles; @@ -919,6 +937,8 @@ protected: std::string DefineFlags; std::vector<cmValueWithOrigin> IncludeDirectoriesEntries; + std::vector<cmValueWithOrigin> CompileOptionsEntries; + std::vector<cmValueWithOrigin> CompileDefinitionsEntries; // Track the value of the computed DEFINITIONS property. void AddDefineFlag(const char*, std::string&); @@ -1022,6 +1042,26 @@ private: bool GeneratingBuildSystem; + /** + * Old version of GetSourceFileWithOutput(const char*) kept for + * backward-compatibility. It implements a linear search and support + * relative file paths. It is used as a fall back by + * GetSourceFileWithOutput(const char*). + */ + cmSourceFile *LinearGetSourceFileWithOutput(const char *cname); + + // A map for fast output to input look up. +#if defined(CMAKE_BUILD_WITH_CMAKE) + typedef cmsys::hash_map<std::string, cmSourceFile*> OutputToSourceMap; +#else + typedef std::map<std::string, cmSourceFile*> OutputToSourceMap; +#endif + OutputToSourceMap OutputToSource; + + void UpdateOutputToSourceMap(std::vector<std::string> const& outputs, + cmSourceFile* source); + void UpdateOutputToSourceMap(std::string const& output, + cmSourceFile* source); }; //---------------------------------------------------------------------------- diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index b7a454b17..3a71bd6eb 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -30,11 +30,8 @@ cmMakefileExecutableTargetGenerator this->TargetNamePDB, this->ConfigName); this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target, - this->TargetNameOut, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); - this->MacContentDirectory = - this->OSXBundleGenerator->GetMacContentDirectory(); } //---------------------------------------------------------------------------- @@ -103,11 +100,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Construct the full path version of the names. std::string outpath = this->Target->GetDirectory(this->ConfigName); - outpath += "/"; if(this->Target->IsAppBundleOnApple()) { this->OSXBundleGenerator->CreateAppBundle(targetName, outpath); } + outpath += "/"; std::string outpathImp; if(relink) { @@ -341,13 +338,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) vars.CMTarget = this->Target; vars.Language = linkLanguage; vars.Objects = buildObjs.c_str(); - std::string objdir = cmake::GetCMakeFilesDirectoryPostSlash(); - objdir += this->Target->GetName(); - objdir += ".dir"; - objdir = this->Convert(objdir.c_str(), - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::SHELL); - vars.ObjectDir = objdir.c_str(); + std::string objectDir = this->Target->GetSupportDirectory(); + objectDir = this->Convert(objectDir.c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); + vars.ObjectDir = objectDir.c_str(); vars.Target = targetOutPathReal.c_str(); vars.TargetPDB = targetOutPathPDB.c_str(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 5b4e4d774..ffe68e5b2 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -24,19 +24,14 @@ cmMakefileLibraryTargetGenerator ::cmMakefileLibraryTargetGenerator(cmTarget* target): cmMakefileTargetGenerator(target) { - cmOSXBundleGenerator::PrepareTargetProperties(this->Target); - this->CustomCommandDriver = OnDepends; this->Target->GetLibraryNames( this->TargetNameOut, this->TargetNameSO, this->TargetNameReal, this->TargetNameImport, this->TargetNamePDB, this->ConfigName); this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target, - this->TargetNameOut, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); - this->MacContentDirectory = - this->OSXBundleGenerator->GetMacContentDirectory(); } //---------------------------------------------------------------------------- @@ -149,12 +144,8 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() } std::string extraFlags; - this->LocalGenerator->AppendFlags - (extraFlags,this->Target->GetProperty("STATIC_LIBRARY_FLAGS")); - std::string staticLibraryFlagsConfig = "STATIC_LIBRARY_FLAGS_"; - staticLibraryFlagsConfig += cmSystemTools::UpperCase(this->ConfigName); - this->LocalGenerator->AppendFlags - (extraFlags, this->Target->GetProperty(staticLibraryFlagsConfig.c_str())); + this->LocalGenerator->GetStaticLibraryFlags(extraFlags, + cmSystemTools::UpperCase(this->ConfigName), this->Target); this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), false); } @@ -292,14 +283,15 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules std::string outpathImp; if(this->Target->IsFrameworkOnApple()) { - outpath = this->MacContentDirectory; - this->OSXBundleGenerator->CreateFramework(targetName); + outpath = this->Target->GetDirectory(this->ConfigName); + this->OSXBundleGenerator->CreateFramework(targetName, outpath); + outpath += "/"; } else if(this->Target->IsCFBundleOnApple()) { outpath = this->Target->GetDirectory(this->ConfigName); - outpath += "/"; this->OSXBundleGenerator->CreateCFBundle(targetName, outpath); + outpath += "/"; } else if(relink) { @@ -585,13 +577,11 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules vars.CMTarget = this->Target; vars.Language = linkLanguage; vars.Objects = buildObjs.c_str(); - std::string objdir = cmake::GetCMakeFilesDirectoryPostSlash(); - objdir += this->Target->GetName(); - objdir += ".dir"; - objdir = this->Convert(objdir.c_str(), - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::SHELL); - vars.ObjectDir = objdir.c_str(); + std::string objectDir = this->Target->GetSupportDirectory(); + objectDir = this->Convert(objectDir.c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); + vars.ObjectDir = objectDir.c_str(); vars.Target = targetOutPathReal.c_str(); vars.LinkLibraries = linkLibs.c_str(); vars.ObjectsQuoted = buildObjs.c_str(); @@ -727,7 +717,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules commands1.clear(); // Add a rule to create necessary symlinks for the library. - if(targetOutPath != targetOutPathReal) + // Frameworks are handled by cmOSXBundleGenerator. + if(targetOutPath != targetOutPathReal && !this->Target->IsFrameworkOnApple()) { std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library "; symlink += targetOutPathReal; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 4220ae148..5e6c54822 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -271,6 +271,9 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l) this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang, this->ConfigName); + this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target, + lang); + // Add include directory flags. this->AddIncludeFlags(flags, lang); @@ -282,6 +285,10 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l) this->LocalGenerator-> AppendFlags(flags,this->GetFrameworkFlags().c_str()); + // Add target-specific flags. + this->LocalGenerator->AddCompileOptions(flags, this->Target, + lang, this->ConfigName); + ByLanguageMap::value_type entry(l, flags); i = this->FlagsByLanguage.insert(entry).first; } @@ -302,9 +309,8 @@ std::string cmMakefileTargetGenerator::GetDefines(const std::string &l) } // Add preprocessor definitions for this target and configuration. - this->LocalGenerator->AppendDefines - (defines, this->Target->GetCompileDefinitions( - this->LocalGenerator->ConfigurationName.c_str())); + this->LocalGenerator->AddCompileDefinitions(defines, this->Target, + this->LocalGenerator->ConfigurationName.c_str()); std::string definesString; this->LocalGenerator->JoinDefines(defines, definesString, lang); @@ -339,15 +345,6 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() *this->FlagFileStream << *l << "_DEFINES = " << this->GetDefines(*l) << "\n\n"; } - - // Add target-specific flags. - if(this->Target->GetProperty("COMPILE_FLAGS")) - { - std::string flags; - this->LocalGenerator->AppendFlags - (flags, this->Target->GetProperty("COMPILE_FLAGS")); - *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n"; - } } @@ -357,7 +354,7 @@ cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator() (cmSourceFile& source, const char* pkgloc) { // Skip OS X content when not building a Framework or Bundle. - if(this->Generator->MacContentDirectory.empty()) + if(!this->Generator->GetTarget()->IsBundleOnApple()) { return; } @@ -532,37 +529,8 @@ cmMakefileTargetGenerator langFlags += "_FLAGS)"; this->LocalGenerator->AppendFlags(flags, langFlags.c_str()); - // Add target-specific flags. - if(this->Target->GetProperty("COMPILE_FLAGS")) - { - std::string langIncludeExpr = "CMAKE_"; - langIncludeExpr += lang; - langIncludeExpr += "_FLAG_REGEX"; - const char* regex = this->Makefile-> - GetDefinition(langIncludeExpr.c_str()); - if(regex) - { - cmsys::RegularExpression r(regex); - std::vector<std::string> args; - cmSystemTools::ParseWindowsCommandLine( - this->Target->GetProperty("COMPILE_FLAGS"), - args); - for(std::vector<std::string>::iterator i = args.begin(); - i != args.end(); ++i) - { - if(r.find(i->c_str())) - { - this->LocalGenerator->AppendFlags - (flags, i->c_str()); - } - } - } - else - { - this->LocalGenerator->AppendFlags - (flags, this->Target->GetProperty("COMPILE_FLAGS")); - } - } + std::string configUpper = + cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName); // Add Fortran format flags. if(strcmp(lang, "Fortran") == 0) @@ -594,8 +562,6 @@ cmMakefileTargetGenerator << compile_defs << "\n" << "\n"; } - std::string configUpper = - cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName); std::string defPropName = "COMPILE_DEFINITIONS_"; defPropName += configUpper; if(const char* config_compile_defs = @@ -672,7 +638,7 @@ cmMakefileTargetGenerator cmLocalGenerator::NONE, cmLocalGenerator::SHELL).c_str(); vars.Object = shellObj.c_str(); - std::string objectDir = cmSystemTools::GetFilenamePath(obj); + std::string objectDir = this->Target->GetSupportDirectory(); objectDir = this->Convert(objectDir.c_str(), cmLocalGenerator::START_OUTPUT, cmLocalGenerator::SHELL); @@ -1869,7 +1835,8 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, lang, config); std::string includeFlags = - this->LocalGenerator->GetIncludeFlags(includes, lang, useResponseFile); + this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget, + lang, useResponseFile); if(includeFlags.empty()) { return; diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 2798e5462..f7a1e2e56 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -233,7 +233,6 @@ protected: std::string TargetNamePDB; // Mac OS X content info. - std::string MacContentDirectory; std::set<cmStdString> MacContentFolders; cmOSXBundleGenerator* OSXBundleGenerator; MacOSXContentGeneratorType* MacOSXContentGenerator; diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 4456aa794..1fa4e95b6 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -25,11 +25,8 @@ cmMakefileUtilityTargetGenerator { this->CustomCommandDriver = OnUtility; this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target, - this->TargetNameOut, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); - this->MacContentDirectory = - this->OSXBundleGenerator->GetMacContentDirectory(); } //---------------------------------------------------------------------------- diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 7e48cd716..57adeba23 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -36,8 +36,6 @@ cmNinjaNormalTargetGenerator(cmTarget* target) , TargetNamePDB() , TargetLinkLanguage(0) { - cmOSXBundleGenerator::PrepareTargetProperties(target); - this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName()); if (target->GetType() == cmTarget::EXECUTABLE) target->GetExecutableNames(this->TargetNameOut, @@ -61,7 +59,6 @@ cmNinjaNormalTargetGenerator(cmTarget* target) } this->OSXBundleGenerator = new cmOSXBundleGenerator(target, - this->TargetNameOut, this->GetConfigName()); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } @@ -74,7 +71,8 @@ cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() void cmNinjaNormalTargetGenerator::Generate() { if (!this->TargetLinkLanguage) { - cmSystemTools::Error("CMake can not determine linker language for target:", + cmSystemTools::Error("CMake can not determine linker language for " + "target: ", this->GetTarget()->GetName()); return; } @@ -267,7 +265,8 @@ cmNinjaNormalTargetGenerator rspcontent); } - if (this->TargetNameOut != this->TargetNameReal) { + if (this->TargetNameOut != this->TargetNameReal && + !this->GetTarget()->IsFrameworkOnApple()) { std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND"), @@ -383,24 +382,32 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() if (this->GetTarget()->IsAppBundleOnApple()) { // Create the app bundle - std::string outpath; + std::string outpath = + this->GetTarget()->GetDirectory(this->GetConfigName()); this->OSXBundleGenerator->CreateAppBundle(this->TargetNameOut, outpath); // Calculate the output path - targetOutput = outpath + this->TargetNameOut; + targetOutput = outpath; + targetOutput += "/"; + targetOutput += this->TargetNameOut; targetOutput = this->ConvertToNinjaPath(targetOutput.c_str()); - targetOutputReal = outpath + this->TargetNameReal; + targetOutputReal = outpath; + targetOutputReal += "/"; + targetOutputReal += this->TargetNameReal; targetOutputReal = this->ConvertToNinjaPath(targetOutputReal.c_str()); } else if (this->GetTarget()->IsFrameworkOnApple()) { // Create the library framework. - this->OSXBundleGenerator->CreateFramework(this->TargetNameOut); + std::string outpath = + this->GetTarget()->GetDirectory(this->GetConfigName()); + this->OSXBundleGenerator->CreateFramework(this->TargetNameOut, outpath); } else if(this->GetTarget()->IsCFBundleOnApple()) { // Create the core foundation bundle. - std::string outpath; + std::string outpath = + this->GetTarget()->GetDirectory(this->GetConfigName()); this->OSXBundleGenerator->CreateCFBundle(this->TargetNameOut, outpath); } @@ -505,7 +512,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() const std::string objPath = GetTarget()->GetSupportDirectory(); vars["OBJECT_DIR"] = ConvertToNinjaPath(objPath.c_str()); EnsureDirectoryExists(objPath); - // ar.exe can't handle backslashes in rsp files (implictly used by gcc) + // ar.exe can't handle backslashes in rsp files (implicitly used by gcc) std::string& linkLibraries = vars["LINK_LIBRARIES"]; std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/'); } @@ -572,32 +579,38 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() #endif } + //Get the global generator as we are going to be call WriteBuild numerous + //times in the following section + cmGlobalNinjaGenerator* globalGenerator = this->GetGlobalGenerator(); + + const std::string rspfile = std::string (cmake::GetCMakeFilesDirectoryPostSlash()) + this->GetTarget()->GetName() + ".rsp"; // Write the build statement for this target. - cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(), - comment.str(), - this->LanguageLinkerRule(), - outputs, - explicitDeps, - implicitDeps, - emptyDeps, - vars, - rspfile, - commandLineLengthLimit); - - if (targetOutput != targetOutputReal) { + globalGenerator->WriteBuild(this->GetBuildFileStream(), + comment.str(), + this->LanguageLinkerRule(), + outputs, + explicitDeps, + implicitDeps, + emptyDeps, + vars, + rspfile, + commandLineLengthLimit); + + if (targetOutput != targetOutputReal && + !this->GetTarget()->IsFrameworkOnApple()) { if (targetType == cmTarget::EXECUTABLE) { - cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(), + globalGenerator->WriteBuild(this->GetBuildFileStream(), "Create executable symlink " + targetOutput, - "CMAKE_SYMLINK_EXECUTABLE", - cmNinjaDeps(1, targetOutput), - cmNinjaDeps(1, targetOutputReal), - emptyDeps, - emptyDeps, - symlinkVars); + "CMAKE_SYMLINK_EXECUTABLE", + cmNinjaDeps(1, targetOutput), + cmNinjaDeps(1, targetOutputReal), + emptyDeps, + emptyDeps, + symlinkVars); } else { cmNinjaDeps symlinks; const std::string soName = this->GetTargetFilePath(this->TargetNameSO); @@ -609,30 +622,30 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() symlinks.push_back(soName); } symlinks.push_back(targetOutput); - cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(), - "Create library symlink " + targetOutput, - "CMAKE_SYMLINK_LIBRARY", - symlinks, - cmNinjaDeps(1, targetOutputReal), - emptyDeps, - emptyDeps, - symlinkVars); + globalGenerator->WriteBuild(this->GetBuildFileStream(), + "Create library symlink " + targetOutput, + "CMAKE_SYMLINK_LIBRARY", + symlinks, + cmNinjaDeps(1, targetOutputReal), + emptyDeps, + emptyDeps, + symlinkVars); } } if (!this->TargetNameImport.empty()) { // Since using multiple outputs would mess up the $out variable, use an // alias for the import library. - cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(), - "Alias for import library.", - cmNinjaDeps(1, targetOutputImplib), - cmNinjaDeps(1, targetOutputReal)); + globalGenerator->WritePhonyBuild(this->GetBuildFileStream(), + "Alias for import library.", + cmNinjaDeps(1, targetOutputImplib), + cmNinjaDeps(1, targetOutputReal)); } // Add aliases for the file name and the target name. - this->GetGlobalGenerator()->AddTargetAlias(this->TargetNameOut, + globalGenerator->AddTargetAlias(this->TargetNameOut, this->GetTarget()); - this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(), + globalGenerator->AddTargetAlias(this->GetTargetName(), this->GetTarget()); } @@ -643,11 +656,11 @@ void cmNinjaNormalTargetGenerator::WriteObjectLibStatement() cmNinjaDeps outputs; this->GetLocalGenerator()->AppendTargetOutputs(this->GetTarget(), outputs); cmNinjaDeps depends = this->GetObjects(); - cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(), - "Object library " - + this->GetTargetName(), - outputs, - depends); + this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(), + "Object library " + + this->GetTargetName(), + outputs, + depends); // Add aliases for the target name. this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(), diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 3fb823cb0..9c8b4810b 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -150,15 +150,19 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, language.c_str(), this->GetConfigName()); + this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target, + language.c_str()); + // Add include directory flags. + const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); { std::vector<std::string> includes; - const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, language.c_str(), config); std::string includeFlags = - this->LocalGenerator->GetIncludeFlags(includes, language.c_str(), + this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget, + language.c_str(), language == "RC" ? true : false); // full include paths for RC // needed by cmcldeps if(cmGlobalNinjaGenerator::IsMinGW()) @@ -171,36 +175,8 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, this->LocalGenerator->AppendFlags(flags, this->Makefile->GetDefineFlags()); // Add target-specific flags. - if(this->Target->GetProperty("COMPILE_FLAGS")) - { - std::string langIncludeExpr = "CMAKE_"; - langIncludeExpr += language; - langIncludeExpr += "_FLAG_REGEX"; - const char* regex = this->Makefile-> - GetDefinition(langIncludeExpr.c_str()); - if(regex) - { - cmsys::RegularExpression r(regex); - std::vector<std::string> args; - cmSystemTools::ParseWindowsCommandLine( - this->Target->GetProperty("COMPILE_FLAGS"), - args); - for(std::vector<std::string>::iterator i = args.begin(); - i != args.end(); ++i) - { - if(r.find(i->c_str())) - { - this->LocalGenerator->AppendFlags - (flags, i->c_str()); - } - } - } - else - { - this->LocalGenerator->AppendFlags - (flags, this->Target->GetProperty("COMPILE_FLAGS")); - } - } + this->LocalGenerator->AddCompileOptions(flags, this->Target, + language.c_str(), config); // Add source file specific flags. this->LocalGenerator->AppendFlags(flags, @@ -226,9 +202,8 @@ ComputeDefines(cmSourceFile *source, const std::string& language) } // Add preprocessor definitions for this target and configuration. - this->LocalGenerator->AppendDefines - (defines, - this->Target->GetCompileDefinitions(this->GetConfigName())); + this->LocalGenerator->AddCompileDefinitions(defines, this->Target, + this->GetConfigName()); this->LocalGenerator->AppendDefines (defines, source->GetProperty("COMPILE_DEFINITIONS")); @@ -568,12 +543,10 @@ cmNinjaTargetGenerator vars["DEP_FILE"] = objectFileName + ".d";; EnsureParentDirectoryExists(objectFileName); - std::string objectDir = cmSystemTools::GetFilenamePath(objectFileName); - objectDir = this->GetLocalGenerator()->Convert(objectDir.c_str(), - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::SHELL); - vars["OBJECT_DIR"] = objectDir; - + std::string objectDir = this->Target->GetSupportDirectory(); + vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( + ConvertToNinjaPath(objectDir.c_str()).c_str(), + cmLocalGenerator::SHELL); this->SetMsvcTargetPdbVariable(vars); @@ -623,24 +596,24 @@ cmNinjaTargetGenerator sourceFileName); } - cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(), - comment, - rule, - outputs, - explicitDeps, - implicitDeps, - orderOnlyDeps, - vars); + this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), + comment, + rule, + outputs, + explicitDeps, + implicitDeps, + orderOnlyDeps, + vars); if(const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) { std::vector<std::string> outputList; cmSystemTools::ExpandListArgument(objectOutputs, outputList); std::transform(outputList.begin(), outputList.end(), outputList.begin(), MapToNinjaPath()); - cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(), - "Additional output files.", - outputList, - outputs); + this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(), + "Additional output files.", + outputList, + outputs); } } @@ -701,7 +674,7 @@ cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( cmSourceFile& source, const char* pkgloc) { // Skip OS X content when not building a Framework or Bundle. - if(this->Generator->OSXBundleGenerator->GetMacContentDirectory().empty()) + if(!this->Generator->GetTarget()->IsBundleOnApple()) { return; } diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 9c2fd13dd..755ce6edc 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -61,11 +61,11 @@ void cmNinjaUtilityTargetGenerator::Generate() this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(), deps); if (commands.empty()) { - cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(), - "Utility command for " - + this->GetTargetName(), - outputs, - deps); + this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(), + "Utility command for " + + this->GetTargetName(), + outputs, + deps); } else { std::string command = this->GetLocalGenerator()->BuildCommandLine(commands); @@ -105,10 +105,11 @@ void cmNinjaUtilityTargetGenerator::Generate() cmNinjaDeps(1, utilCommandName), deps); - cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(), - "", - outputs, - cmNinjaDeps(1, utilCommandName)); + this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(), + "", + outputs, + cmNinjaDeps(1, utilCommandName) + ); } this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(), diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index 42fad0742..a475c7cfa 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -16,38 +16,19 @@ #include <cassert> -void cmOSXBundleGenerator::PrepareTargetProperties(cmTarget* target) -{ - if(target->IsCFBundleOnApple()) - { - target->SetProperty("PREFIX", ""); - target->SetProperty("SUFFIX", ""); - } -} - //---------------------------------------------------------------------------- cmOSXBundleGenerator:: cmOSXBundleGenerator(cmTarget* target, - std::string targetNameOut, const char* configName) : Target(target) , Makefile(target->GetMakefile()) , LocalGenerator(Makefile->GetLocalGenerator()) - , TargetNameOut(targetNameOut) , ConfigName(configName) - , MacContentDirectory() - , FrameworkVersion() , MacContentFolders(0) { if (this->MustSkip()) return; - this->MacContentDirectory = - this->Target->GetMacContentDirectory(this->ConfigName, - /*implib*/ false, - /*includeMacOS*/ false); - if(this->Target->IsFrameworkOnApple()) - this->FrameworkVersion = this->Target->GetFrameworkVersion(); } //---------------------------------------------------------------------------- @@ -57,41 +38,60 @@ bool cmOSXBundleGenerator::MustSkip() } //---------------------------------------------------------------------------- -void cmOSXBundleGenerator::CreateAppBundle(std::string& targetName, +void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, std::string& outpath) { if (this->MustSkip()) return; // Compute bundle directory names. - outpath = this->MacContentDirectory; - outpath += "MacOS"; - cmSystemTools::MakeDirectory(outpath.c_str()); - outpath += "/"; - this->Makefile->AddCMakeOutputFile(outpath.c_str()); + std::string out = outpath; + out += "/"; + out += this->Target->GetAppBundleDirectory(this->ConfigName, false); + cmSystemTools::MakeDirectory(out.c_str()); + this->Makefile->AddCMakeOutputFile(out); + + std::string newoutpath = out; // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = this->MacContentDirectory + "Info.plist"; + std::string plist = outpath; + plist += "/"; + plist += this->Target->GetAppBundleDirectory(this->ConfigName, true); + plist += "/Info.plist"; this->LocalGenerator->GenerateAppleInfoPList(this->Target, targetName.c_str(), plist.c_str()); - this->Makefile->AddCMakeOutputFile(plist.c_str()); + this->Makefile->AddCMakeOutputFile(plist); + outpath = newoutpath; } //---------------------------------------------------------------------------- -void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) +void cmOSXBundleGenerator::CreateFramework( + const std::string& targetName, const std::string& outpath) { if (this->MustSkip()) return; assert(this->MacContentFolders); + // Compute the location of the top-level foo.framework directory. + std::string contentdir = outpath + "/" + + this->Target->GetFrameworkDirectory(this->ConfigName, true); + contentdir += "/"; + + std::string newoutpath = outpath + "/" + + this->Target->GetFrameworkDirectory(this->ConfigName, false); + + std::string frameworkVersion = this->Target->GetFrameworkVersion(); + // Configure the Info.plist file into the Resources directory. this->MacContentFolders->insert("Resources"); - std::string plist = this->MacContentDirectory + "Resources/Info.plist"; + std::string plist = newoutpath; + plist += "/Resources/Info.plist"; + std::string name = cmSystemTools::GetFilenameName(targetName); this->LocalGenerator->GenerateFrameworkInfoPList(this->Target, - targetName.c_str(), + name.c_str(), plist.c_str()); // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to @@ -99,50 +99,42 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) std::string oldName; std::string newName; - // Compute the location of the top-level foo.framework directory. - std::string top = this->Target->GetDirectory(this->ConfigName); - top += "/"; - top += this->TargetNameOut; - top += ".framework/"; // Make foo.framework/Versions - std::string versions = top; + std::string versions = contentdir; versions += "Versions"; cmSystemTools::MakeDirectory(versions.c_str()); // Make foo.framework/Versions/version - std::string version = versions; - version += "/"; - version += this->FrameworkVersion; - cmSystemTools::MakeDirectory(version.c_str()); + cmSystemTools::MakeDirectory(newoutpath.c_str()); // Current -> version - oldName = this->FrameworkVersion; + oldName = frameworkVersion; newName = versions; newName += "/Current"; cmSystemTools::RemoveFile(newName.c_str()); cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str()); - this->Makefile->AddCMakeOutputFile(newName.c_str()); + this->Makefile->AddCMakeOutputFile(newName); // foo -> Versions/Current/foo oldName = "Versions/Current/"; - oldName += this->TargetNameOut; - newName = top; - newName += this->TargetNameOut; + oldName += name; + newName = contentdir; + newName += name; cmSystemTools::RemoveFile(newName.c_str()); cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str()); - this->Makefile->AddCMakeOutputFile(newName.c_str()); + this->Makefile->AddCMakeOutputFile(newName); // Resources -> Versions/Current/Resources if(this->MacContentFolders->find("Resources") != this->MacContentFolders->end()) { oldName = "Versions/Current/Resources"; - newName = top; + newName = contentdir; newName += "Resources"; cmSystemTools::RemoveFile(newName.c_str()); cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str()); - this->Makefile->AddCMakeOutputFile(newName.c_str()); + this->Makefile->AddCMakeOutputFile(newName); } // Headers -> Versions/Current/Headers @@ -150,11 +142,11 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) this->MacContentFolders->end()) { oldName = "Versions/Current/Headers"; - newName = top; + newName = contentdir; newName += "Headers"; cmSystemTools::RemoveFile(newName.c_str()); cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str()); - this->Makefile->AddCMakeOutputFile(newName.c_str()); + this->Makefile->AddCMakeOutputFile(newName); } // PrivateHeaders -> Versions/Current/PrivateHeaders @@ -162,36 +154,37 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName) this->MacContentFolders->end()) { oldName = "Versions/Current/PrivateHeaders"; - newName = top; + newName = contentdir; newName += "PrivateHeaders"; cmSystemTools::RemoveFile(newName.c_str()); cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str()); - this->Makefile->AddCMakeOutputFile(newName.c_str()); + this->Makefile->AddCMakeOutputFile(newName); } } //---------------------------------------------------------------------------- -void cmOSXBundleGenerator::CreateCFBundle(std::string& targetName, - std::string& outpath) +void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, + const std::string& root) { if (this->MustSkip()) return; // Compute bundle directory names. - outpath = this->MacContentDirectory; - outpath += "MacOS"; - cmSystemTools::MakeDirectory(outpath.c_str()); - outpath += "/"; - this->Makefile->AddCMakeOutputFile(outpath.c_str()); + std::string out = root; + out += "/"; + out += this->Target->GetCFBundleDirectory(this->ConfigName, false); + cmSystemTools::MakeDirectory(out.c_str()); + this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = this->MacContentDirectory; - plist += "Info.plist"; + std::string plist = + this->Target->GetCFBundleDirectory(this->ConfigName, true); + plist += "/Info.plist"; this->LocalGenerator->GenerateAppleInfoPList(this->Target, targetName.c_str(), plist.c_str()); - this->Makefile->AddCMakeOutputFile(plist.c_str()); + this->Makefile->AddCMakeOutputFile(plist); } //---------------------------------------------------------------------------- @@ -220,7 +213,11 @@ std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc) { // Construct the full path to the content subdirectory. - std::string macdir = this->MacContentDirectory; + + std::string macdir = + this->Target->GetMacContentDirectory(this->ConfigName, + /*implib*/ false); + macdir += "/"; macdir += pkgloc; cmSystemTools::MakeDirectory(macdir.c_str()); diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index 01e3cbeb4..ec82b9a15 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -25,15 +25,20 @@ class cmLocalGenerator; class cmOSXBundleGenerator { public: - static void PrepareTargetProperties(cmTarget* target); - cmOSXBundleGenerator(cmTarget* target, - std::string targetNameOut, const char* configName); - void CreateAppBundle(std::string& targetName, std::string& outpath); - void CreateFramework(std::string const& targetName); - void CreateCFBundle(std::string& targetName, std::string& outpath); + // create an app bundle at a given root, and return + // the directory within the bundle that contains the executable + void CreateAppBundle(const std::string& targetName, std::string& root); + + // create a framework at a given root + void CreateFramework(const std::string& targetName, + const std::string& root); + + // create a cf bundle at a given root + void CreateCFBundle(const std::string& targetName, + const std::string& root); struct MacOSXContentGeneratorType { @@ -46,10 +51,6 @@ public: MacOSXContentGeneratorType* generator); std::string InitMacOSXContentDirectory(const char* pkgloc); - std::string GetMacContentDirectory() const - { return this->MacContentDirectory; } - std::string GetFrameworkVersion() const - { return this->FrameworkVersion; } void SetMacContentFolders(std::set<cmStdString>* macContentFolders) { this->MacContentFolders = macContentFolders; } @@ -60,10 +61,7 @@ private: cmTarget* Target; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; - std::string TargetNameOut; const char* ConfigName; - std::string MacContentDirectory; - std::string FrameworkVersion; std::set<cmStdString>* MacContentFolders; }; diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 6e41768b0..022082519 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -36,8 +36,26 @@ public: OD(od), GlobalGenerator(od->GlobalGenerator) { this->FullPath = file; - this->Directory = cmSystemTools::GetFilenamePath(file); - this->FileName = cmSystemTools::GetFilenameName(file); + + if(file.rfind(".framework") != std::string::npos) + { + cmsys::RegularExpression splitFramework; + splitFramework.compile("^(.*)/(.*).framework/(.*)$"); + if(splitFramework.find(file) && + (std::string::npos != + splitFramework.match(3).find(splitFramework.match(2)))) + { + this->Directory = splitFramework.match(1); + this->FileName = + std::string(file.begin() + this->Directory.size() + 1, file.end()); + } + } + + if(this->FileName.empty()) + { + this->Directory = cmSystemTools::GetFilenamePath(file); + this->FileName = cmSystemTools::GetFilenameName(file); + } } virtual ~cmOrderDirectoriesConstraint() {} @@ -305,6 +323,19 @@ void cmOrderDirectories::AddRuntimeLibrary(std::string const& fullPath, if(!this->ImplicitDirectories.empty()) { std::string dir = cmSystemTools::GetFilenamePath(fullPath); + + if(fullPath.rfind(".framework") != std::string::npos) + { + cmsys::RegularExpression splitFramework; + splitFramework.compile("^(.*)/(.*).framework/(.*)$"); + if(splitFramework.find(fullPath) && + (std::string::npos != + splitFramework.match(3).find(splitFramework.match(2)))) + { + dir = splitFramework.match(1); + } + } + if(this->ImplicitDirectories.find(dir) != this->ImplicitDirectories.end()) { diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 831e92e92..a823f0595 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -440,7 +440,8 @@ cmPolicies::cmPolicies() this->DefinePolicy( CMP0016, "CMP0016", - "target_link_libraries() reports error if only argument is not a target.", + "target_link_libraries() reports error if its only argument " + "is not a target.", "In CMake 2.8.2 and lower the target_link_libraries() command silently " "ignored if it was called with only one argument, and this argument " "wasn't a valid target. " @@ -452,7 +453,7 @@ cmPolicies::cmPolicies() "Prefer files from the CMake module directory when including from there.", "Starting with CMake 2.8.4, if a cmake-module shipped with CMake (i.e. " "located in the CMake module directory) calls include() or " - "find_package(), the files located in the the CMake module directory are " + "find_package(), the files located in the CMake module directory are " "preferred over the files in CMAKE_MODULE_PATH. " "This makes sure that the modules belonging to " "CMake always get those files included which they expect, and against " @@ -529,6 +530,77 @@ cmPolicies::cmPolicies() "The NEW behavior for this policy is to link executables to " "qtmain.lib automatically when they link to QtCore IMPORTED target.", 2,8,11,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0021, "CMP0021", + "Fatal error on relative paths in INCLUDE_DIRECTORIES target property.", + "CMake 2.8.10.2 and lower allowed the INCLUDE_DIRECTORIES target " + "property to contain relative paths. The base path for such relative " + "entries is not well defined. CMake 2.8.12 issues a FATAL_ERROR if the " + "INCLUDE_DIRECTORIES property contains a relative path." + "\n" + "The OLD behavior for this policy is not to warn about relative paths in " + "the INCLUDE_DIRECTORIES target property. " + "The NEW behavior for this policy is to issue a FATAL_ERROR if " + "INCLUDE_DIRECTORIES contains a relative path.", + 2,8,12,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0022, "CMP0022", + "INTERFACE_LINK_LIBRARIES defines the link interface.", + "CMake 2.8.11 constructed the 'link interface' of a target from " + "properties matching (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?. " + "The modern way to specify config-sensitive content is to use generator " + "expressions and the IMPORTED_ prefix makes uniform processing of the " + "link interface with generator expressions impossible. The " + "INTERFACE_LINK_LIBRARIES target property was introduced as a " + "replacement in CMake 2.8.12. This new property is named consistently " + "with the INTERFACE_COMPILE_DEFINITIONS, INTERFACE_INCLUDE_DIRECTORIES " + "and INTERFACE_COMPILE_OPTIONS properties. For in-build targets, CMake " + "will use the INTERFACE_LINK_LIBRARIES property as the source of the " + "link interface only if policy CMP0022 is NEW. " + "When exporting a target which has this policy set to NEW, only the " + "INTERFACE_LINK_LIBRARIES property will be processed and generated for " + "the IMPORTED target by default. A new option to the install(EXPORT) " + "and export commands allows export of the old-style properties for " + "compatibility with downstream users of CMake versions older than " + "2.8.12. " + "The target_link_libraries command will no longer populate the " + "properties matching LINK_INTERFACE_LIBRARIES(_<CONFIG>)? if this policy " + "is NEW." + "\n" + "The OLD behavior for this policy is to ignore the " + "INTERFACE_LINK_LIBRARIES property for in-build targets. " + "The NEW behavior for this policy is to use the INTERFACE_LINK_LIBRARIES " + "property for in-build targets, and ignore the old properties matching " + "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?.", + 2,8,12,0, cmPolicies::WARN); + + this->DefinePolicy( + CMP0023, "CMP0023", + "Plain and keyword target_link_libraries signatures cannot be mixed.", + "CMake 2.8.12 introduced the target_link_libraries signature using " + "the PUBLIC, PRIVATE, and INTERFACE keywords to generalize the " + "LINK_PUBLIC and LINK_PRIVATE keywords introduced in CMake 2.8.7. " + "Use of signatures with any of these keywords sets the link interface " + "of a target explicitly, even if empty. " + "This produces confusing behavior when used in combination with the " + "historical behavior of the plain target_link_libraries signature. " + "For example, consider the code:\n" + " target_link_libraries(mylib A)\n" + " target_link_libraries(mylib PRIVATE B)\n" + "After the first line the link interface has not been set explicitly " + "so CMake would use the link implementation, A, as the link interface. " + "However, the second line sets the link interface to empty. " + "In order to avoid this subtle behavior CMake now prefers to disallow " + "mixing the plain and keyword signatures of target_link_libraries for " + "a single target." + "\n" + "The OLD behavior for this policy is to allow keyword and plain " + "target_link_libraries signatures to be mixed. " + "The NEW behavior for this policy is to not to allow mixing of the " + "keyword and plain signatures.", + 2,8,12,0, cmPolicies::WARN); } cmPolicies::~cmPolicies() @@ -770,7 +842,7 @@ std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id) { cmSystemTools::Error( "Request for error text for undefined policy!"); - return "Request for warning text for undefined policy!"; + return "Request for error text for undefined policy!"; } cmOStringStream error; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index c11af0714..5b843a9ad 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -70,6 +70,10 @@ public: /// instead. CMP0019, ///< No variable re-expansion in include and link info CMP0020, ///< Automatically link Qt executables to qtmain target + CMP0021, ///< Fatal error on relative paths in INCLUDE_DIRECTORIES + /// target property + CMP0022, ///< INTERFACE_LINK_LIBRARIES defines the link interface + CMP0023, ///< Disallow mixing keyword and plain tll signatures /** \brief Always the last entry. * diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h index a53cb3fb8..9547c4c8f 100644 --- a/Source/cmProjectCommand.h +++ b/Source/cmProjectCommand.h @@ -71,7 +71,13 @@ public: "language \"NONE\" all checks for any language can be disabled. " "If a variable exists called CMAKE_PROJECT_<projectName>_INCLUDE, " "the file pointed to by that variable will be included as the last step " - "of the project command."; + "of the project command." + "\n" + "The top-level CMakeLists.txt file for a project must contain a " + "literal, direct call to the project() command; loading one through " + "the include() command is not sufficient. " + "If no such call exists CMake will implicitly add one to the top that " + "enables the default languages (C and CXX)."; } cmTypeMacro(cmProjectCommand, cmCommand); diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx index a1fa31f2a..93e39abeb 100644 --- a/Source/cmQtAutomoc.cxx +++ b/Source/cmQtAutomoc.cxx @@ -152,10 +152,46 @@ bool cmQtAutomoc::InitializeMocSourceFile(cmTarget* target) return true; } -void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) +static void GetCompileDefinitionsAndDirectories(cmTarget *target, + const char * config, + std::string &incs, + std::string &defs) { cmMakefile* makefile = target->GetMakefile(); cmLocalGenerator* localGen = makefile->GetLocalGenerator(); + std::vector<std::string> includeDirs; + cmGeneratorTarget gtgt(target); + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667 + localGen->GetIncludeDirectories(includeDirs, >gt, "CXX", config, false); + const char* sep = ""; + incs = ""; + for(std::vector<std::string>::const_iterator incDirIt = includeDirs.begin(); + incDirIt != includeDirs.end(); + ++incDirIt) + { + incs += sep; + sep = ";"; + incs += *incDirIt; + } + + std::set<std::string> defines; + localGen->AddCompileDefinitions(defines, target, config); + + sep = ""; + for(std::set<std::string>::const_iterator defIt = defines.begin(); + defIt != defines.end(); + ++defIt) + { + defs += sep; + sep = ";"; + defs += *defIt; + } +} + +void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) +{ + cmMakefile* makefile = target->GetMakefile(); const char* targetName = target->GetName(); bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); @@ -175,6 +211,7 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) currentLine.push_back("-E"); currentLine.push_back("cmake_automoc"); currentLine.push_back(targetDir); + currentLine.push_back("$<CONFIGURATION>"); cmCustomCommandLines commandLines; commandLines.push_back(currentLine); @@ -188,6 +225,7 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) #if defined(_WIN32) && !defined(__CYGWIN__) bool usePRE_BUILD = false; + cmLocalGenerator* localGen = makefile->GetLocalGenerator(); cmGlobalGenerator* gg = localGen->GetGlobalGenerator(); if(strstr(gg->GetName(), "Visual Studio")) { @@ -219,8 +257,18 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) automocTargetName.c_str(), true, workingDirectory.c_str(), depends, commandLines, false, automocComment.c_str()); - // inherit FOLDER property from target (#13688) - copyTargetProperty(automocTarget, target, "FOLDER"); + // Set target folder + const char* automocFolder = makefile->GetCMakeInstance()->GetProperty( + "AUTOMOC_TARGETS_FOLDER"); + if (automocFolder && *automocFolder) + { + automocTarget->SetProperty("FOLDER", automocFolder); + } + else + { + // inherit FOLDER property from target (#13688) + copyTargetProperty(automocTarget, target, "FOLDER"); + } target->AddUtility(automocTargetName.c_str()); } @@ -263,36 +311,7 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) } } - - std::vector<std::string> includeDirs; - cmGeneratorTarget gtgt(target); - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667 - localGen->GetIncludeDirectories(includeDirs, >gt, "CXX", 0, false); - std::string _moc_incs = ""; - const char* sep = ""; - for(std::vector<std::string>::const_iterator incDirIt = includeDirs.begin(); - incDirIt != includeDirs.end(); - ++incDirIt) - { - _moc_incs += sep; - sep = ";"; - _moc_incs += *incDirIt; - } - - const char* tmp = target->GetProperty("COMPILE_DEFINITIONS"); - std::string _moc_compile_defs; - if (tmp) - { - _moc_compile_defs = target->GetCompileDefinitions(0); - } - tmp = makefile->GetProperty("COMPILE_DEFINITIONS"); - if (tmp) - { - _moc_compile_defs += ";"; - _moc_compile_defs += tmp; - } - tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); + const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); std::string _moc_options = (tmp!=0 ? tmp : ""); // forget the variables added here afterwards again: @@ -301,10 +320,6 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) makefile->AddDefinition("_moc_target_name", cmLocalGenerator::EscapeForCMake(automocTargetName.c_str()).c_str()); - makefile->AddDefinition("_moc_incs", - cmLocalGenerator::EscapeForCMake(_moc_incs.c_str()).c_str()); - makefile->AddDefinition("_moc_compile_defs", - cmLocalGenerator::EscapeForCMake(_moc_compile_defs.c_str()).c_str()); makefile->AddDefinition("_moc_options", cmLocalGenerator::EscapeForCMake(_moc_options.c_str()).c_str()); makefile->AddDefinition("_moc_files", @@ -313,6 +328,89 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) cmLocalGenerator::EscapeForCMake(_moc_headers.c_str()).c_str()); makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); + std::string _moc_incs; + std::string _moc_compile_defs; + std::vector<std::string> configs; + const char *config = makefile->GetConfigurations(configs); + GetCompileDefinitionsAndDirectories(target, config, + _moc_incs, _moc_compile_defs); + + makefile->AddDefinition("_moc_incs", + cmLocalGenerator::EscapeForCMake(_moc_incs.c_str()).c_str()); + makefile->AddDefinition("_moc_compile_defs", + cmLocalGenerator::EscapeForCMake(_moc_compile_defs.c_str()).c_str()); + + std::map<std::string, std::string> configIncludes; + std::map<std::string, std::string> configDefines; + + for (std::vector<std::string>::const_iterator li = configs.begin(); + li != configs.end(); ++li) + { + std::string config_moc_incs; + std::string config_moc_compile_defs; + GetCompileDefinitionsAndDirectories(target, li->c_str(), + config_moc_incs, + config_moc_compile_defs); + if (config_moc_incs != _moc_incs) + { + configIncludes["_moc_incs_" + *li] = + cmLocalGenerator::EscapeForCMake(config_moc_incs.c_str()); + if(_moc_incs.empty()) + { + _moc_incs = config_moc_incs; + } + } + if (config_moc_compile_defs != _moc_compile_defs) + { + configDefines["_moc_compile_defs_" + *li] = + cmLocalGenerator::EscapeForCMake(config_moc_compile_defs.c_str()); + if(_moc_compile_defs.empty()) + { + _moc_compile_defs = config_moc_compile_defs; + } + } + } + + const char *qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR"); + if (!qtVersion) + { + qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR"); + } + if (const char *targetQtVersion = + target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", 0)) + { + qtVersion = targetQtVersion; + } + if (qtVersion) + { + makefile->AddDefinition("_target_qt_version", qtVersion); + } + + { + const char *qtMoc = makefile->GetSafeDefinition("QT_MOC_EXECUTABLE"); + makefile->AddDefinition("_qt_moc_executable", qtMoc); + } + + if (strcmp(qtVersion, "5") == 0) + { + cmTarget *qt5Moc = makefile->FindTargetToUse("Qt5::moc"); + if (!qt5Moc) + { + cmSystemTools::Error("Qt5::moc target not found ", + automocTargetName.c_str()); + return; + } + makefile->AddDefinition("_qt_moc_executable", qt5Moc->GetLocation(0)); + } + else + { + if (strcmp(qtVersion, "4") != 0) + { + cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and " + "Qt 5 ", automocTargetName.c_str()); + } + } + const char* cmakeRoot = makefile->GetSafeDefinition("CMAKE_ROOT"); std::string inputFile = cmakeRoot; inputFile += "/Modules/AutomocInfo.cmake.in"; @@ -320,17 +418,50 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target) outputFile += "/AutomocInfo.cmake"; makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true, false); + + if (!configDefines.empty() || !configIncludes.empty()) + { + std::ofstream infoFile(outputFile.c_str(), std::ios::app); + if ( !infoFile ) + { + std::string error = "Internal CMake error when trying to open file: "; + error += outputFile.c_str(); + error += " for writing."; + cmSystemTools::Error(error.c_str()); + return; + } + if (!configDefines.empty()) + { + for (std::map<std::string, std::string>::iterator + it = configDefines.begin(), end = configDefines.end(); + it != end; ++it) + { + infoFile << "SET(AM_MOC_COMPILE_DEFINITIONS_" << it->first << + " " << it->second << ")\n"; + } + } + if (!configIncludes.empty()) + { + for (std::map<std::string, std::string>::iterator + it = configIncludes.begin(), end = configIncludes.end(); + it != end; ++it) + { + infoFile << "SET(AM_MOC_INCLUDES_" << it->first << + " " << it->second << ")\n"; + } + } + } } -bool cmQtAutomoc::Run(const char* targetDirectory) +bool cmQtAutomoc::Run(const char* targetDirectory, const char *config) { bool success = true; cmake cm; cmGlobalGenerator* gg = this->CreateGlobalGenerator(&cm, targetDirectory); cmMakefile* makefile = gg->GetCurrentLocalGenerator()->GetMakefile(); - this->ReadAutomocInfoFile(makefile, targetDirectory); + this->ReadAutomocInfoFile(makefile, targetDirectory, config); this->ReadOldMocDefinitionsFile(makefile, targetDirectory); this->Init(); @@ -367,7 +498,8 @@ cmGlobalGenerator* cmQtAutomoc::CreateGlobalGenerator(cmake* cm, bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile, - const char* targetDirectory) + const char* targetDirectory, + const char *config) { std::string filename(cmSystemTools::CollapseFullPath(targetDirectory)); cmSystemTools::ConvertToUnixSlashes(filename); @@ -375,7 +507,7 @@ bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile, if (!makefile->ReadListFile(0, filename.c_str())) { - cmSystemTools::Error("Error processing file:", filename.c_str()); + cmSystemTools::Error("Error processing file: ", filename.c_str()); return false; } @@ -392,9 +524,26 @@ bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile, this->Srcdir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_SOURCE_DIR"); this->Builddir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_BINARY_DIR"); this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE"); - this->MocCompileDefinitionsStr = makefile->GetSafeDefinition( - "AM_MOC_COMPILE_DEFINITIONS"); - this->MocIncludesStr = makefile->GetSafeDefinition("AM_MOC_INCLUDES"); + std::string compileDefsPropOrig = "AM_MOC_COMPILE_DEFINITIONS"; + std::string compileDefsProp = compileDefsPropOrig; + if(config) + { + compileDefsProp += "_"; + compileDefsProp += config; + } + const char *compileDefs = makefile->GetDefinition(compileDefsProp.c_str()); + this->MocCompileDefinitionsStr = compileDefs ? compileDefs + : makefile->GetSafeDefinition(compileDefsPropOrig.c_str()); + std::string includesPropOrig = "AM_MOC_INCLUDES"; + std::string includesProp = includesPropOrig; + if(config) + { + includesProp += "_"; + includesProp += config; + } + const char *includes = makefile->GetDefinition(includesProp.c_str()); + this->MocIncludesStr = includes ? includes + : makefile->GetSafeDefinition(includesPropOrig.c_str()); this->MocOptionsStr = makefile->GetSafeDefinition("AM_MOC_OPTIONS"); this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR"); this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR"); @@ -696,7 +845,7 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename, std::string ownMocHeaderFile; std::string::size_type matchOffset = 0; - // first a simply string check for "moc" is *much* faster than the regexp, + // first a simple string check for "moc" is *much* faster than the regexp, // and if the string search already fails, we don't have to try the // expensive regexp if ((strstr(contentsString.c_str(), "moc") != NULL) @@ -870,7 +1019,7 @@ void cmQtAutomoc::StrictParseCppFile(const std::string& absFilename, bool dotMocIncluded = false; std::string::size_type matchOffset = 0; - // first a simply string check for "moc" is *much* faster than the regexp, + // first a simple string check for "moc" is *much* faster than the regexp, // and if the string search already fails, we don't have to try the // expensive regexp if ((strstr(contentsString.c_str(), "moc") != NULL) diff --git a/Source/cmQtAutomoc.h b/Source/cmQtAutomoc.h index 01b68fc54..ebeeb0eee 100644 --- a/Source/cmQtAutomoc.h +++ b/Source/cmQtAutomoc.h @@ -21,7 +21,7 @@ class cmQtAutomoc { public: cmQtAutomoc(); - bool Run(const char* targetDirectory); + bool Run(const char* targetDirectory, const char *config); bool InitializeMocSourceFile(cmTarget* target); void SetupAutomocTarget(cmTarget* target); @@ -31,7 +31,8 @@ private: const char* targetDirectory); bool ReadAutomocInfoFile(cmMakefile* makefile, - const char* targetDirectory); + const char* targetDirectory, + const char *config); bool ReadOldMocDefinitionsFile(cmMakefile* makefile, const char* targetDirectory); void WriteOldMocDefinitionsFile(const char* targetDirectory); diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index cc10840fd..42078605a 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -84,12 +84,14 @@ bool cmSetPropertyCommand { doing = DoingNone; this->AppendMode = true; + this->Remove = false; this->AppendAsString = false; } else if(*arg == "APPEND_STRING") { doing = DoingNone; this->AppendMode = true; + this->Remove = false; this->AppendAsString = true; } else if(doing == DoingNames) @@ -160,7 +162,7 @@ bool cmSetPropertyCommand::HandleGlobalMode() } if(this->AppendMode) { - cm->AppendProperty(name, value, this->AppendAsString); + cm->AppendProperty(name, value ? value : "", this->AppendAsString); } else { @@ -226,7 +228,7 @@ bool cmSetPropertyCommand::HandleDirectoryMode() } if(this->AppendMode) { - mf->AppendProperty(name, value, this->AppendAsString); + mf->AppendProperty(name, value ? value : "", this->AppendAsString); } else { @@ -242,6 +244,11 @@ bool cmSetPropertyCommand::HandleTargetMode() for(std::set<cmStdString>::const_iterator ni = this->Names.begin(); ni != this->Names.end(); ++ni) { + if (this->Makefile->IsAlias(ni->c_str())) + { + this->SetError("can not be used on an ALIAS target."); + return false; + } if(cmTarget* target = this->Makefile->FindTargetToUse(ni->c_str())) { // Handle the current target. diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx index a2b50a8ef..78ef393cc 100644 --- a/Source/cmSetTargetPropertiesCommand.cxx +++ b/Source/cmSetTargetPropertiesCommand.cxx @@ -72,6 +72,11 @@ bool cmSetTargetPropertiesCommand int i; for(i = 0; i < numFiles; ++i) { + if (this->Makefile->IsAlias(args[i].c_str())) + { + this->SetError("can not be used on an ALIAS target."); + return false; + } bool ret = cmSetTargetPropertiesCommand::SetOneTarget (args[i].c_str(),propertyPairs,this->Makefile); if (!ret) diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h index 9dd7848d3..cf9c19350 100644 --- a/Source/cmSetTargetPropertiesCommand.h +++ b/Source/cmSetTargetPropertiesCommand.h @@ -104,7 +104,7 @@ public: "are common values for this property." "\n" "For shared libraries VERSION and SOVERSION can be used to specify " - "the build version and api version respectively. When building or " + "the build version and API version respectively. When building or " "installing appropriate symlinks are created if the platform " "supports symlinks and the linker supports so-names. " "If only one of both is specified the missing is assumed to have " diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 1d4b0c8b4..8bb7d96f5 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -483,7 +483,7 @@ void cmSourceFile::DefineProperties(cmake *cm) "the source file is. If it is not set the language is determined " "based on the file extension. Typical values are CXX C etc. Setting " "this property for a file means this file will be compiled. " - "Do not set this for header or files that should not be compiled."); + "Do not set this for headers or files that should not be compiled."); cm->DefineProperty ("LOCATION", cmProperty::SOURCE_FILE, @@ -551,7 +551,7 @@ void cmSourceFile::DefineProperties(cmake *cm) "Some packages can wrap source files into alternate languages " "to provide additional functionality. For example, C++ code " "can be wrapped into Java or Python etc using SWIG etc. " - "If WRAP_EXCLUDE is set to true (1 etc) that indicates then " + "If WRAP_EXCLUDE is set to true (1 etc) that indicates that " "this source file should not be wrapped."); } diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index e49edd878..68ba13f62 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -93,6 +93,10 @@ bool cmStringCommand { return this->HandleTimestampCommand(args); } + else if(subCommand == "MAKE_C_IDENTIFIER") + { + return this->HandleMakeCIdentifierCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -530,8 +534,12 @@ void cmStringCommand::ClearMatches(cmMakefile* mf) { char name[128]; sprintf(name, "CMAKE_MATCH_%d", i); - mf->AddDefinition(name, ""); - mf->MarkVariableAsUsed(name); + const char* s = mf->GetDefinition(name); + if(s && *s != 0) + { + mf->AddDefinition(name, ""); + mf->MarkVariableAsUsed(name); + } } } @@ -540,10 +548,14 @@ void cmStringCommand::StoreMatches(cmMakefile* mf,cmsys::RegularExpression& re) { for (unsigned int i=0; i<10; i++) { - char name[128]; - sprintf(name, "CMAKE_MATCH_%d", i); - mf->AddDefinition(name, re.match(i).c_str()); - mf->MarkVariableAsUsed(name); + std::string m = re.match(i); + if(m.size() > 0) + { + char name[128]; + sprintf(name, "CMAKE_MATCH_%d", i); + mf->AddDefinition(name, re.match(i).c_str()); + mf->MarkVariableAsUsed(name); + } } } @@ -755,6 +767,24 @@ bool cmStringCommand } //---------------------------------------------------------------------------- +bool cmStringCommand +::HandleMakeCIdentifierCommand(std::vector<std::string> const& args) +{ + if(args.size() != 3) + { + this->SetError("sub-command MAKE_C_IDENTIFIER requires two arguments."); + return false; + } + + const std::string& input = args[1]; + const std::string& variableName = args[2]; + + this->Makefile->AddDefinition(variableName.c_str(), + cmSystemTools::MakeCidentifier(input.c_str()).c_str()); + return true; +} + +//---------------------------------------------------------------------------- bool cmStringCommand::HandleStripCommand( std::vector<std::string> const& args) { diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index 802e0b850..f584cfdbf 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -94,6 +94,7 @@ public: " [RANDOM_SEED <seed>] <output variable>)\n" " string(FIND <string> <substring> <output variable> [REVERSE])\n" " string(TIMESTAMP <output variable> [<format string>] [UTC])\n" + " string(MAKE_C_IDENTIFIER <input string> <output variable>)\n" "REGEX MATCH will match the regular expression once and store the " "match in the output variable.\n" "REGEX MATCHALL will match the regular expression as many times as " @@ -176,7 +177,9 @@ public: "and copied to the output as-is.\n" "If no explicit <format string> is given it will default to:\n" " %Y-%m-%dT%H:%M:%S for local time.\n" - " %Y-%m-%dT%H:%M:%SZ for UTC."; + " %Y-%m-%dT%H:%M:%SZ for UTC.\n" + "MAKE_C_IDENTIFIER will write a string which can be used as an " + "identifier in C."; } cmTypeMacro(cmStringCommand, cmCommand); @@ -200,6 +203,7 @@ protected: bool HandleRandomCommand(std::vector<std::string> const& args); bool HandleFindCommand(std::vector<std::string> const& args); bool HandleTimestampCommand(std::vector<std::string> const& args); + bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args); class RegexReplacement { diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx index 0cfe7722d..e497b4642 100644 --- a/Source/cmSubdirCommand.cxx +++ b/Source/cmSubdirCommand.cxx @@ -64,7 +64,7 @@ bool cmSubdirCommand else { std::string error = "Incorrect SUBDIRS command. Directory: "; - error += *i + " does not exists."; + error += *i + " does not exist."; this->SetError(error.c_str()); res = false; } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 67f302391..9ec49382a 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -638,6 +638,12 @@ bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command, cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); } + if (outputflag == OUTPUT_PASSTHROUGH) + { + cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1); + cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1); + } + cmsysProcess_SetTimeout(cp, timeout); cmsysProcess_Execute(cp); @@ -645,7 +651,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command, char* data; int length; int pipe; - if ( output || outputflag != OUTPUT_NONE ) + if(outputflag != OUTPUT_PASSTHROUGH && (output || outputflag != OUTPUT_NONE)) { while((pipe = cmsysProcess_WaitForData(cp, &data, &length, 0)) > 0) { @@ -1594,6 +1600,40 @@ std::string cmSystemTools::RelativePath(const char* local, const char* remote) return cmsys::SystemTools::RelativePath(local, remote); } +std::string cmSystemTools::CollapseCombinedPath(std::string const& dir, + std::string const& file) +{ + if(dir.empty() || dir == ".") + { + return file; + } + + std::vector<std::string> dirComponents; + std::vector<std::string> fileComponents; + cmSystemTools::SplitPath(dir.c_str(), dirComponents); + cmSystemTools::SplitPath(file.c_str(), fileComponents); + + if(fileComponents.empty()) + { + return dir; + } + if(fileComponents[0] != "") + { + // File is not a relative path. + return file; + } + + std::vector<std::string>::iterator i = fileComponents.begin()+1; + while(i != fileComponents.end() && *i == ".." && dirComponents.size() > 1) + { + ++i; // Remove ".." file component. + dirComponents.pop_back(); // Remove last dir component. + } + + dirComponents.insert(dirComponents.end(), i, fileComponents.end()); + return cmSystemTools::JoinPath(dirComponents); +} + #ifdef CMAKE_BUILD_WITH_CMAKE //---------------------------------------------------------------------- bool cmSystemTools::UnsetEnv(const char* value) @@ -1662,6 +1702,7 @@ cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment() void cmSystemTools::EnableVSConsoleOutput() { +#ifdef _WIN32 // Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not // display output to the console unless this environment variable is // set. We need it to capture the output of these build tools. @@ -1669,8 +1710,15 @@ void cmSystemTools::EnableVSConsoleOutput() // either of these executables where NAME is created with // CreateNamedPipe. This would bypass the internal buffering of the // output and allow it to be captured on the fly. -#ifdef _WIN32 cmSystemTools::PutEnv("vsconsoleoutput=1"); + +# ifdef CMAKE_BUILD_WITH_CMAKE + // VS sets an environment variable to tell MS tools like "cl" to report + // output through a backdoor pipe instead of stdout/stderr. Unset the + // environment variable to close this backdoor for any path of process + // invocations that passes through CMake so we can capture the output. + cmSystemTools::UnsetEnv("VS_UNICODE_OUTPUT"); +# endif #endif } @@ -1951,7 +1999,7 @@ bool extract_tar(const char* outFileName, bool verbose, { cmSystemTools::Error("Problem with archive_write_header(): ", archive_error_string(ext)); - cmSystemTools::Error("Current file:", + cmSystemTools::Error("Current file: ", archive_entry_pathname(entry)); break; } @@ -2413,6 +2461,38 @@ bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath, } //---------------------------------------------------------------------------- +bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath, + std::string& soname) +{ + std::vector<cmStdString> cmds; + cmds.push_back("otool"); + cmds.push_back("-D"); + cmds.push_back(fullPath.c_str()); + + std::string output; + if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE)) + { + cmds.insert(cmds.begin(), "-r"); + cmds.insert(cmds.begin(), "xcrun"); + if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE)) + { + return false; + } + } + + std::vector<std::string> strs = cmSystemTools::tokenize(output, "\n"); + // otool returns extra lines reporting multiple install names + // in case the binary is multi-arch and none of the architectures + // is native (e.g. i386;ppc on x86_64) + if(strs.size() >= 2) + { + soname = strs[1]; + return true; + } + return false; +} + +//---------------------------------------------------------------------------- #if defined(CMAKE_USE_ELF_PARSER) std::string::size_type cmSystemToolsFindRPath(std::string const& have, std::string const& want) @@ -2659,13 +2739,18 @@ bool cmSystemTools::ChangeRPath(std::string const& file, bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, const char* lhss, const char* rhss) { - unsigned int lhs[4] = {0,0,0,0}; - unsigned int rhs[4] = {0,0,0,0}; - sscanf(lhss, "%u.%u.%u.%u", &lhs[0], &lhs[1], &lhs[2], &lhs[3]); - sscanf(rhss, "%u.%u.%u.%u", &rhs[0], &rhs[1], &rhs[2], &rhs[3]); + // Parse out up to 8 components. + unsigned int lhs[8] = {0,0,0,0,0,0,0,0}; + unsigned int rhs[8] = {0,0,0,0,0,0,0,0}; + sscanf(lhss, "%u.%u.%u.%u.%u.%u.%u.%u", + &lhs[0], &lhs[1], &lhs[2], &lhs[3], + &lhs[4], &lhs[5], &lhs[6], &lhs[7]); + sscanf(rhss, "%u.%u.%u.%u.%u.%u.%u.%u", + &rhs[0], &rhs[1], &rhs[2], &rhs[3], + &rhs[4], &rhs[5], &rhs[6], &rhs[7]); // Do component-wise comparison. - for(unsigned int i=0; i < 4; ++i) + for(unsigned int i=0; i < 8; ++i) { if(lhs[i] < rhs[i]) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 0b2def216..9d7dae9ef 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -56,7 +56,7 @@ public: typedef void (*ErrorCallback)(const char*, const char*, bool&, void*); /** - * Set the function used by GUI's to display error messages + * Set the function used by GUIs to display error messages * Function gets passed: message as a const char*, * title as a const char*, and a reference to bool that when * set to false, will disable furthur messages (cancel). @@ -211,7 +211,7 @@ public: * user-viewable output from the program being run will be generated. * OUTPUT_MERGE is the legacy behaviour where stdout and stderr are merged * into stdout. OUTPUT_NORMAL passes through the output to stdout/stderr as - * it was received. + * it was received. OUTPUT_PASSTHROUGH passes through the original handles. * * If timeout is specified, the command will be terminated after * timeout expires. Timeout is specified in seconds. @@ -230,7 +230,8 @@ public: { OUTPUT_NONE = 0, OUTPUT_MERGE, - OUTPUT_NORMAL + OUTPUT_NORMAL, + OUTPUT_PASSTHROUGH }; static bool RunSingleCommand(const char* command, std::string* output = 0, int* retVal = 0, const char* dir = 0, @@ -274,7 +275,7 @@ public: static bool GetRunCommandOutput() { return s_DisableRunCommandOutput; } /** - * Come constants for different file formats. + * Some constants for different file formats. */ enum FileFormat { NO_FILE_FORMAT = 0, @@ -365,6 +366,12 @@ public: */ static std::string RelativePath(const char* local, const char* remote); + /** Joins two paths while collapsing x/../ parts + * For example CollapseCombinedPath("a/b/c", "../../d") results in "a/d" + */ + static std::string CollapseCombinedPath(std::string const& dir, + std::string const& file); + #ifdef CMAKE_BUILD_WITH_CMAKE /** Remove an environment variable */ static bool UnsetEnv(const char* value); @@ -439,6 +446,10 @@ public: static bool GuessLibrarySOName(std::string const& fullPath, std::string& soname); + /** Try to guess the install name of a shared library. */ + static bool GuessLibraryInstallName(std::string const& fullPath, + std::string& soname); + /** Try to set the RPATH in an ELF binary. */ static bool ChangeRPath(std::string const& file, std::string const& oldRPath, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index d14bfcaf6..4ba6c1981 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -83,10 +83,12 @@ class cmTargetInternals public: cmTargetInternals() { + this->PolicyWarnedCMP0022 = false; this->SourceFileFlagsConstructed = false; } cmTargetInternals(cmTargetInternals const& r) { + this->PolicyWarnedCMP0022 = false; this->SourceFileFlagsConstructed = false; // Only some of these entries are part of the object state. // Others not copied here are result caches. @@ -109,6 +111,7 @@ public: typedef std::map<TargetConfigPair, OptionalLinkInterface> LinkInterfaceMapType; LinkInterfaceMapType LinkInterfaceMap; + bool PolicyWarnedCMP0022; typedef std::map<cmStdString, cmTarget::OutputInfo> OutputInfoMapType; OutputInfoMapType OutputInfoMap; @@ -130,31 +133,37 @@ public: typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType; SourceEntriesType SourceEntries; - struct IncludeDirectoriesEntry { - IncludeDirectoriesEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge, + struct TargetPropertyEntry { + TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge, const std::string &targetName = std::string()) : ge(cge), TargetName(targetName) {} const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge; - std::vector<std::string> CachedIncludes; + std::vector<std::string> CachedEntries; const std::string TargetName; }; - std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries; - std::vector<cmValueWithOrigin> LinkInterfaceIncludeDirectoriesEntries; + std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; + std::vector<TargetPropertyEntry*> CompileOptionsEntries; + std::vector<TargetPropertyEntry*> CompileDefinitionsEntries; + std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries; - std::map<std::string, std::vector<IncludeDirectoriesEntry*> > + std::map<std::string, std::vector<TargetPropertyEntry*> > CachedLinkInterfaceIncludeDirectoriesEntries; - std::map<std::string, std::string> CachedLinkInterfaceCompileDefinitions; + std::map<std::string, std::vector<TargetPropertyEntry*> > + CachedLinkInterfaceCompileOptionsEntries; + std::map<std::string, std::vector<TargetPropertyEntry*> > + CachedLinkInterfaceCompileDefinitionsEntries; std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone; std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone; + std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone; }; //---------------------------------------------------------------------------- void deleteAndClear( - std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries) + std::vector<cmTargetInternals::TargetPropertyEntry*> &entries) { - for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator + for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator it = entries.begin(), end = entries.end(); it != end; ++it) @@ -167,10 +176,10 @@ void deleteAndClear( //---------------------------------------------------------------------------- void deleteAndClear( std::map<std::string, - std::vector<cmTargetInternals::IncludeDirectoriesEntry*> > &entries) + std::vector<cmTargetInternals::TargetPropertyEntry*> > &entries) { for (std::map<std::string, - std::vector<cmTargetInternals::IncludeDirectoriesEntry*> >::iterator + std::vector<cmTargetInternals::TargetPropertyEntry*> >::iterator it = entries.begin(), end = entries.end(); it != end; ++it) { deleteAndClear(it->second); @@ -180,17 +189,22 @@ void deleteAndClear( //---------------------------------------------------------------------------- cmTargetInternals::~cmTargetInternals() { - deleteAndClear(CachedLinkInterfaceIncludeDirectoriesEntries); + deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries); + deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries); + deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries); } //---------------------------------------------------------------------------- cmTarget::cmTarget() { +#define INITIALIZE_TARGET_POLICY_MEMBER(POLICY) \ + this->PolicyStatus ## POLICY = cmPolicies::WARN; + + CM_FOR_EACH_TARGET_POLICY(INITIALIZE_TARGET_POLICY_MEMBER) + +#undef INITIALIZE_TARGET_POLICY_MEMBER + this->Makefile = 0; - this->PolicyStatusCMP0003 = cmPolicies::WARN; - this->PolicyStatusCMP0004 = cmPolicies::WARN; - this->PolicyStatusCMP0008 = cmPolicies::WARN; - this->PolicyStatusCMP0020 = cmPolicies::WARN; this->LinkLibrariesAnalyzed = false; this->HaveInstallRule = false; this->DLLPlatform = false; @@ -198,6 +212,8 @@ cmTarget::cmTarget() this->IsImportedTarget = false; this->BuildInterfaceIncludesAppended = false; this->DebugIncludesDone = false; + this->DebugCompileOptionsDone = false; + this->DebugCompileDefinitionsDone = false; } //---------------------------------------------------------------------------- @@ -229,7 +245,9 @@ void cmTarget::DefineProperties(cmake *cm) "AUTOMOC_MOC_OPTIONS property.\n" "By setting the CMAKE_AUTOMOC_RELAXED_MODE variable to TRUE the rules " "for searching the files which will be processed by moc can be relaxed. " - "See the documentation for this variable for more details."); + "See the documentation for this variable for more details.\n" + "The global property AUTOMOC_TARGETS_FOLDER can be used to group the " + "automoc targets together in an IDE, e.g. in MSVS."); cm->DefineProperty ("AUTOMOC_MOC_OPTIONS", cmProperty::TARGET, @@ -285,6 +303,30 @@ void cmTarget::DefineProperties(cmake *cm) "This is the configuration-specific version of COMPILE_DEFINITIONS."); cm->DefineProperty + ("COMPILE_OPTIONS", cmProperty::TARGET, + "List of options to pass to the compiler.", + "This property specifies the list of options specified " + "so far for this property. " + "This property exists on directories and targets." + "\n" + "The target property values are used by the generators to set " + "the options for the compiler.\n" + "Contents of COMPILE_OPTIONS may use \"generator expressions\" with " + "the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + + cm->DefineProperty + ("INTERFACE_COMPILE_OPTIONS", cmProperty::TARGET, + "List of interface options to pass to the compiler.", + "Targets may populate this property to publish the compile options " + "required to compile against the headers for the target. Consuming " + "targets can add entries to their own COMPILE_OPTIONS property such " + "as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_OPTIONS> to use the " + "compile options specified in the interface of 'foo'." + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + + cm->DefineProperty ("DEFINE_SYMBOL", cmProperty::TARGET, "Define a symbol when compiling this target's sources.", "DEFINE_SYMBOL sets the name of the preprocessor symbol defined when " @@ -292,7 +334,7 @@ void cmTarget::DefineProperties(cmake *cm) "If not set here then it is set to target_EXPORTS by default " "(with some substitutions if the target is not a valid C " "identifier). This is useful for headers to know whether they are " - "being included from inside their library our outside to properly " + "being included from inside their library or outside to properly " "setup dllexport/dllimport decorations. "); cm->DefineProperty @@ -438,7 +480,7 @@ void cmTarget::DefineProperties(cmake *cm) "imported library. " "The list " "should be disjoint from the list of interface libraries in the " - "IMPORTED_LINK_INTERFACE_LIBRARIES property. On platforms requiring " + "INTERFACE_LINK_LIBRARIES property. On platforms requiring " "dependent shared libraries to be found at link time CMake uses this " "list to add appropriate files or paths to the link command line. " "Ignored for non-imported targets."); @@ -459,7 +501,10 @@ void cmTarget::DefineProperties(cmake *cm) "The libraries will be included on the link line for the target. " "Unlike the LINK_INTERFACE_LIBRARIES property, this property applies " "to all imported target types, including STATIC libraries. " - "This property is ignored for non-imported targets."); + "This property is ignored for non-imported targets.\n" + "This property is ignored if the target also has a non-empty " + "INTERFACE_LINK_LIBRARIES property.\n" + "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead."); cm->DefineProperty ("IMPORTED_LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET, @@ -467,7 +512,10 @@ void cmTarget::DefineProperties(cmake *cm) "Configuration names correspond to those provided by the project " "from which the target is imported. " "If set, this property completely overrides the generic property " - "for the named configuration."); + "for the named configuration.\n" + "This property is ignored if the target also has a non-empty " + "INTERFACE_LINK_LIBRARIES property.\n" + "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead."); cm->DefineProperty ("IMPORTED_LINK_INTERFACE_LANGUAGES", cmProperty::TARGET, @@ -700,7 +748,11 @@ void cmTarget::DefineProperties(cmake *cm) "file providing the program entry point (main). " "If not set, the language with the highest linker preference " "value is the default. " - "See documentation of CMAKE_<LANG>_LINKER_PREFERENCE variables."); + "See documentation of CMAKE_<LANG>_LINKER_PREFERENCE variables." + "\n" + "If this property is not set by the user, it will be calculated at " + "generate-time by CMake." + ); cm->DefineProperty ("LOCATION", cmProperty::TARGET, @@ -783,7 +835,10 @@ void cmTarget::DefineProperties(cmake *cm) "This property is initialized by the value of the variable " "CMAKE_LINK_INTERFACE_LIBRARIES if it is set when a target is " "created. " - "This property is ignored for STATIC libraries."); + "This property is ignored for STATIC libraries.\n" + "This property is overridden by the INTERFACE_LINK_LIBRARIES property if " + "policy CMP0022 is NEW.\n" + "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead."); cm->DefineProperty ("LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET, @@ -791,7 +846,23 @@ void cmTarget::DefineProperties(cmake *cm) "This is the configuration-specific version of " "LINK_INTERFACE_LIBRARIES. " "If set, this property completely overrides the generic property " - "for the named configuration."); + "for the named configuration.\n" + "This property is overridden by the INTERFACE_LINK_LIBRARIES property if " + "policy CMP0022 is NEW.\n" + "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead."); + + cm->DefineProperty + ("INTERFACE_LINK_LIBRARIES", cmProperty::TARGET, + "List public interface libraries for a library.", + "This property contains the list of transitive link dependencies. " + "When the target is linked into another target the libraries " + "listed (and recursively their link interface libraries) will be " + "provided to the other target also. " + "This property is overridden by the LINK_INTERFACE_LIBRARIES or " + "LINK_INTERFACE_LIBRARIES_<CONFIG> property if " + "policy CMP0022 is OLD or unset.\n" + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); cm->DefineProperty ("INTERFACE_INCLUDE_DIRECTORIES", cmProperty::TARGET, @@ -805,6 +876,16 @@ void cmTarget::DefineProperties(cmake *cm) CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); cm->DefineProperty + ("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", cmProperty::TARGET, + "List of public system include directories for a library.", + "Targets may populate this property to publish the include directories " + "which contain system headers, and therefore should not result in " + "compiler warnings. Consuming targets will then mark the same include " + "directories as system headers." + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + + cm->DefineProperty ("INTERFACE_COMPILE_DEFINITIONS", cmProperty::TARGET, "List of public compile definitions for a library.", "Targets may populate this property to publish the compile definitions " @@ -867,6 +948,18 @@ void cmTarget::DefineProperties(cmake *cm) "OSX_ARCHITECTURES."); cm->DefineProperty + ("NAME", cmProperty::TARGET, + "Logical name for the target.", + "Read-only logical name for the target as used by CMake."); + + cm->DefineProperty + ("EXPORT_NAME", cmProperty::TARGET, + "Exported name for target files.", + "This sets the name for the IMPORTED target generated when it this " + "target is is exported. " + "If not set, the logical target name is used by default."); + + cm->DefineProperty ("OUTPUT_NAME", cmProperty::TARGET, "Output name for target files.", "This sets the base name for output files created for an executable or " @@ -879,6 +972,12 @@ void cmTarget::DefineProperties(cmake *cm) "This is the configuration-specific version of OUTPUT_NAME."); cm->DefineProperty + ("ALIASED_TARGET", cmProperty::TARGET, + "Name of target aliased by this target.", + "If this is an ALIAS target, this property contains the name of the " + "target aliased."); + + cm->DefineProperty ("<CONFIG>_OUTPUT_NAME", cmProperty::TARGET, "Old per-configuration target file base name.", "This is a configuration-specific version of OUTPUT_NAME. " @@ -886,9 +985,9 @@ void cmTarget::DefineProperties(cmake *cm) cm->DefineProperty ("PDB_NAME", cmProperty::TARGET, - "Output name for MS debug symbols .pdb file.", + "Output name for MS debug symbols .pdb file from linker.", "Set the base name for debug symbols file created for an " - "executable or library target. " + "executable or shared library target. " "If not set, the logical target name is used by default. " "\n" "This property is not implemented by the Visual Studio 6 generator."); @@ -916,6 +1015,26 @@ void cmTarget::DefineProperties(cmake *cm) "(such as \"lib\") on a library name."); cm->DefineProperty + ("<LANG>_VISIBILITY_PRESET", cmProperty::TARGET, + "Value for symbol visibility compile flags", + "The <LANG>_VISIBILITY_PRESET property determines the value passed in " + "a visibility related compile option, such as -fvisibility= for <LANG>. " + "This property only has an affect for libraries and executables with " + "exports. This property is initialized by the value of the variable " + "CMAKE_<LANG>_VISIBILITY_PRESET if it is set when a target is created."); + + cm->DefineProperty + ("VISIBILITY_INLINES_HIDDEN", cmProperty::TARGET, + "Whether to add a compile flag to hide symbols of inline functions", + "The VISIBILITY_INLINES_HIDDEN property determines whether a flag for " + "hiding symbols for inline functions. the value passed used in " + "a visibility related compile option, such as -fvisibility=. This " + "property only has an affect for libraries and executables with " + "exports. This property is initialized by the value of the variable " + "CMAKE_VISIBILITY_INLINES_HIDDEN if it is set when a target is " + "created."); + + cm->DefineProperty ("POSITION_INDEPENDENT_CODE", cmProperty::TARGET, "Whether to create a position-independent target", "The POSITION_INDEPENDENT_CODE property determines whether position " @@ -1054,7 +1173,7 @@ void cmTarget::DefineProperties(cmake *cm) ("SOVERSION", cmProperty::TARGET, "What version number is this target.", "For shared libraries VERSION and SOVERSION can be used to specify " - "the build version and api version respectively. When building or " + "the build version and API version respectively. When building or " "installing appropriate symlinks are created if the platform " "supports symlinks and the linker supports so-names. " "If only one of both is specified the missing is assumed to have " @@ -1092,7 +1211,7 @@ void cmTarget::DefineProperties(cmake *cm) ("VERSION", cmProperty::TARGET, "What version number is this target.", "For shared libraries VERSION and SOVERSION can be used to specify " - "the build version and api version respectively. When building or " + "the build version and API version respectively. When building or " "installing appropriate symlinks are created if the platform " "supports symlinks and the linker supports so-names. " "If only one of both is specified the missing is assumed to have " @@ -1156,7 +1275,7 @@ void cmTarget::DefineProperties(cmake *cm) cm->DefineProperty ("MACOSX_FRAMEWORK_INFO_PLIST", cmProperty::TARGET, "Specify a custom Info.plist template for a Mac OS X Framework.", - "An library target with FRAMEWORK enabled will be built as a " + "A library target with FRAMEWORK enabled will be built as a " "framework on Mac OS X. " "By default its Info.plist file is created by configuring a template " "called MacOSXFrameworkInfo.plist.in located in the CMAKE_MODULE_PATH. " @@ -1174,6 +1293,15 @@ void cmTarget::DefineProperties(cmake *cm) "hard-code all the settings instead of using the target properties."); cm->DefineProperty + ("MACOSX_RPATH", cmProperty::TARGET, + "Whether to use rpaths on Mac OS X.", + "When this property is set to true, the directory portion of the" + "\"install_name\" field of shared libraries will default to \"@rpath\"." + "Runtime paths will also be embedded in binaries using this target." + "This property is initialized by the value of the variable " + "CMAKE_MACOSX_RPATH if it is set when a target is created."); + + cm->DefineProperty ("ENABLE_EXPORTS", cmProperty::TARGET, "Specify whether an executable exports symbols for loadable modules.", "Normally an executable does not export any symbols because it is " @@ -1247,7 +1375,7 @@ void cmTarget::DefineProperties(cmake *cm) cm->DefineProperty ("GENERATOR_FILE_NAME", cmProperty::TARGET, "Generator's file for this target.", - "An internal property used by some generators to record the name of " + "An internal property used by some generators to record the name of the " "project or dsp file associated with this target. Note that at configure " "time, this property is only set for targets created by " "include_external_msproject()."); @@ -1316,6 +1444,16 @@ void cmTarget::DefineProperties(cmake *cm) "this value with \"ManagedCProj\", for example, in a Visual " "Studio managed C++ unit test project."); cm->DefineProperty + ("VS_GLOBAL_ROOTNAMESPACE", cmProperty::TARGET, + "Visual Studio project root namespace.", + "Sets the \"RootNamespace\" attribute for a generated Visual Studio " + "project. The attribute will be generated only if this is set."); + cm->DefineProperty + ("VS_DOTNET_TARGET_FRAMEWORK_VERSION", cmProperty::TARGET, + "Specify the .NET target framework version.", + "Used to specify the .NET target framework version for C++/CLI. " + "For example, \"v4.5\"."); + cm->DefineProperty ("VS_DOTNET_REFERENCES", cmProperty::TARGET, "Visual Studio managed project .NET references", "Adds one or more semicolon-delimited .NET references to a " @@ -1397,9 +1535,9 @@ void cmTarget::DefineProperties(cmake *cm) cm->DefineProperty ("PDB_OUTPUT_DIRECTORY", cmProperty::TARGET, - "Output directory for MS debug symbols .pdb files.", + "Output directory for MS debug symbols .pdb file from linker.", "This property specifies the directory into which the MS debug symbols " - "will be placed. " + "will be placed by the linker. " "This property is initialized by the value of the variable " "CMAKE_PDB_OUTPUT_DIRECTORY if it is set when a target is created." "\n" @@ -1482,7 +1620,7 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->IsApple = this->Makefile->IsOn("APPLE"); // Setup default property values. - this->SetPropertyDefault("INSTALL_NAME_DIR", ""); + this->SetPropertyDefault("INSTALL_NAME_DIR", 0); this->SetPropertyDefault("INSTALL_RPATH", ""); this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF"); this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF"); @@ -1501,6 +1639,8 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0); this->SetPropertyDefault("WIN32_EXECUTABLE", 0); this->SetPropertyDefault("MACOSX_BUNDLE", 0); + this->SetPropertyDefault("MACOSX_RPATH", 0); + // Collect the set of configuration types. std::vector<std::string> configNames; @@ -1552,6 +1692,29 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->InsertInclude(*it); } + const std::set<cmStdString> parentSystemIncludes = + this->Makefile->GetSystemIncludeDirectories(); + + for (std::set<cmStdString>::const_iterator it + = parentSystemIncludes.begin(); + it != parentSystemIncludes.end(); ++it) + { + this->SystemIncludeDirectories.insert(*it); + } + + const std::vector<cmValueWithOrigin> parentOptions = + this->Makefile->GetCompileOptionsEntries(); + + for (std::vector<cmValueWithOrigin>::const_iterator it + = parentOptions.begin(); it != parentOptions.end(); ++it) + { + this->InsertCompileOption(*it); + } + + this->SetPropertyDefault("C_VISIBILITY_PRESET", 0); + this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0); + this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", 0); + if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY || this->TargetTypeValue == cmTarget::MODULE_LIBRARY) { @@ -1560,14 +1723,13 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0); // Record current policies for later use. - this->PolicyStatusCMP0003 = - this->Makefile->GetPolicyStatus(cmPolicies::CMP0003); - this->PolicyStatusCMP0004 = - this->Makefile->GetPolicyStatus(cmPolicies::CMP0004); - this->PolicyStatusCMP0008 = - this->Makefile->GetPolicyStatus(cmPolicies::CMP0008); - this->PolicyStatusCMP0020 = - this->Makefile->GetPolicyStatus(cmPolicies::CMP0020); +#define CAPTURE_TARGET_POLICY(POLICY) \ + this->PolicyStatus ## POLICY = \ + this->Makefile->GetPolicyStatus(cmPolicies::POLICY); + + CM_FOR_EACH_TARGET_POLICY(CAPTURE_TARGET_POLICY) + +#undef CAPTURE_TARGET_POLICY } //---------------------------------------------------------------------------- @@ -1669,11 +1831,17 @@ bool cmTarget::IsCFBundleOnApple() } //---------------------------------------------------------------------------- +bool cmTarget::IsBundleOnApple() +{ + return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() || + this->IsCFBundleOnApple(); +} + +//---------------------------------------------------------------------------- class cmTargetTraceDependencies { public: - cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal, - const char* vsProjectFile); + cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal); void Trace(); private: cmTarget* Target; @@ -1697,8 +1865,7 @@ private: //---------------------------------------------------------------------------- cmTargetTraceDependencies -::cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal, - const char* vsProjectFile): +::cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal): Target(target), Internal(internal) { // Convenience. @@ -1715,13 +1882,6 @@ cmTargetTraceDependencies this->QueueSource(*si); } - // Queue the VS project file to check dependencies on the rule to - // generate it. - if(vsProjectFile) - { - this->FollowName(vsProjectFile); - } - // Queue pre-build, pre-link, and post-build rule dependencies. this->CheckCustomCommands(this->Target->GetPreBuildCommands()); this->CheckCustomCommands(this->Target->GetPreLinkCommands()); @@ -1940,7 +2100,7 @@ cmTargetTraceDependencies } //---------------------------------------------------------------------------- -void cmTarget::TraceDependencies(const char* vsProjectFile) +void cmTarget::TraceDependencies() { // CMake-generated targets have no dependencies to trace. Normally tracing // would find nothing anyway, but when building CMake itself the "install" @@ -1952,7 +2112,7 @@ void cmTarget::TraceDependencies(const char* vsProjectFile) } // Use a helper object to trace the dependencies. - cmTargetTraceDependencies tracer(this, this->Internal.Get(), vsProjectFile); + cmTargetTraceDependencies tracer(this, this->Internal.Get()); tracer.Trace(); } @@ -2174,8 +2334,10 @@ void cmTarget::MergeLinkLibraries( cmMakefile& mf, i += this->PrevLinkedLibraries.size(); for( ; i != libs.end(); ++i ) { - // We call this so that the dependencies get written to the cache + // This is equivalent to the target_link_libraries plain signature. this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second ); + this->AppendProperty("INTERFACE_LINK_LIBRARIES", + this->GetDebugGeneratorExpressions(i->first.c_str(), i->second).c_str()); } this->PrevLinkedLibraries = libs; } @@ -2331,6 +2493,63 @@ static std::string targetNameGenex(const char *lib) } //---------------------------------------------------------------------------- +bool cmTarget::PushTLLCommandTrace(TLLSignature signature) +{ + bool ret = true; + if (!this->TLLCommands.empty()) + { + if (this->TLLCommands.back().first != signature) + { + ret = false; + } + } + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + this->TLLCommands.push_back(std::make_pair(signature, lfbt)); + return ret; +} + +//---------------------------------------------------------------------------- +void cmTarget::GetTllSignatureTraces(cmOStringStream &s, + TLLSignature sig) const +{ + std::vector<cmListFileBacktrace> sigs; + typedef std::vector<std::pair<TLLSignature, cmListFileBacktrace> > Container; + for(Container::const_iterator it = this->TLLCommands.begin(); + it != this->TLLCommands.end(); ++it) + { + if (it->first == sig) + { + sigs.push_back(it->second); + } + } + if (!sigs.empty()) + { + const char *sigString + = (sig == cmTarget::KeywordTLLSignature ? "keyword" + : "plain"); + s << "The uses of the " << sigString << " signature are here:\n"; + std::set<cmStdString> emitted; + for(std::vector<cmListFileBacktrace>::const_iterator it = sigs.begin(); + it != sigs.end(); ++it) + { + cmListFileBacktrace::const_iterator i = it->begin(); + if(i != it->end()) + { + cmListFileContext const& lfc = *i; + cmOStringStream line; + line << " * " << (lfc.Line? "": " in ") << lfc << std::endl; + if (emitted.insert(line.str()).second) + { + s << line.str(); + } + ++i; + } + } + } +} + +//---------------------------------------------------------------------------- void cmTarget::AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, LinkLibraryType llt) @@ -2407,6 +2626,61 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, //---------------------------------------------------------------------------- void +cmTarget::AddSystemIncludeDirectories(const std::set<cmStdString> &incs) +{ + for(std::set<cmStdString>::const_iterator li = incs.begin(); + li != incs.end(); ++li) + { + this->SystemIncludeDirectories.insert(*li); + } +} + +//---------------------------------------------------------------------------- +void +cmTarget::AddSystemIncludeDirectories(const std::vector<std::string> &incs) +{ + for(std::vector<std::string>::const_iterator li = incs.begin(); + li != incs.end(); ++li) + { + this->SystemIncludeDirectories.insert(*li); + } +} + +//---------------------------------------------------------------------------- +void cmTarget::FinalizeSystemIncludeDirectories() +{ + for (std::vector<cmValueWithOrigin>::const_iterator + it = this->Internal->LinkInterfacePropertyEntries.begin(), + end = this->Internal->LinkInterfacePropertyEntries.end(); + it != end; ++it) + { + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(it->Value); + std::string targetName = cge->Evaluate(this->Makefile, 0, + false, this, 0, 0); + if (!this->Makefile->FindTargetToUse(targetName.c_str())) + { + continue; + } + } + std::string includeGenex = "$<TARGET_PROPERTY:" + + it->Value + ",INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>"; + if (cmGeneratorExpression::Find(it->Value) != std::string::npos) + { + // Because it->Value is a generator expression, ensure that it + // evaluates to the non-empty string before being used in the + // TARGET_PROPERTY expression. + includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">"; + } + this->SystemIncludeDirectories.insert(includeGenex); + } +} + +//---------------------------------------------------------------------------- +void cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) { // There are two key parts of the dependency analysis: (1) @@ -2491,8 +2765,6 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) } } - typedef std::vector< std::string > LinkLine; - // The dependency map. DependencyMap dep_map; @@ -2707,7 +2979,13 @@ void cmTarget::SetProperty(const char* prop, const char* value) { return; } - + if (strcmp(prop, "NAME") == 0) + { + cmOStringStream e; + e << "NAME property is read-only\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) { cmListFileBacktrace lfbt; @@ -2716,19 +2994,49 @@ void cmTarget::SetProperty(const char* prop, const char* value) deleteAndClear(this->Internal->IncludeDirectoriesEntries); cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); this->Internal->IncludeDirectoriesEntries.push_back( - new cmTargetInternals::IncludeDirectoriesEntry(cge)); + new cmTargetInternals::TargetPropertyEntry(cge)); + return; + } + if(strcmp(prop,"COMPILE_OPTIONS") == 0) + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + deleteAndClear(this->Internal->CompileOptionsEntries); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); + this->Internal->CompileOptionsEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); + return; + } + if(strcmp(prop,"COMPILE_DEFINITIONS") == 0) + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + deleteAndClear(this->Internal->CompileDefinitionsEntries); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); + this->Internal->CompileDefinitionsEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); + return; + } + if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported()) + { + cmOStringStream e; + e << "EXPORT_NAME property can't be set on imported targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); return; } if (strcmp(prop, "LINK_LIBRARIES") == 0) { - this->Internal->LinkInterfaceIncludeDirectoriesEntries.clear(); + this->Internal->LinkInterfacePropertyEntries.clear(); if (cmGeneratorExpression::IsValidTargetName(value) || cmGeneratorExpression::Find(value) != std::string::npos) { cmListFileBacktrace lfbt; this->Makefile->GetBacktrace(lfbt); cmValueWithOrigin entry(value, lfbt); - this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry); + this->Internal->LinkInterfacePropertyEntries.push_back(entry); } // Fall through } @@ -2744,13 +3052,46 @@ void cmTarget::AppendProperty(const char* prop, const char* value, { return; } + if (strcmp(prop, "NAME") == 0) + { + cmOStringStream e; + e << "NAME property is read-only\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + return; + } if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0) { cmListFileBacktrace lfbt; this->Makefile->GetBacktrace(lfbt); cmGeneratorExpression ge(lfbt); this->Internal->IncludeDirectoriesEntries.push_back( - new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value))); + new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); + return; + } + if(strcmp(prop,"COMPILE_OPTIONS") == 0) + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + this->Internal->CompileOptionsEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); + return; + } + if(strcmp(prop,"COMPILE_DEFINITIONS") == 0) + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + this->Internal->CompileDefinitionsEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); + return; + } + if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported()) + { + cmOStringStream e; + e << "EXPORT_NAME property can't be set on imported targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); return; } if (strcmp(prop, "LINK_LIBRARIES") == 0) @@ -2761,7 +3102,7 @@ void cmTarget::AppendProperty(const char* prop, const char* value, cmListFileBacktrace lfbt; this->Makefile->GetBacktrace(lfbt); cmValueWithOrigin entry(value, lfbt); - this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry); + this->Internal->LinkInterfacePropertyEntries.push_back(entry); } // Fall through } @@ -2770,6 +3111,26 @@ void cmTarget::AppendProperty(const char* prop, const char* value, } //---------------------------------------------------------------------------- +const char* cmTarget::GetExportName() +{ + const char *exportName = this->GetProperty("EXPORT_NAME"); + + if (exportName && *exportName) + { + if (!cmGeneratorExpression::IsValidTargetName(exportName)) + { + cmOStringStream e; + e << "EXPORT_NAME property \"" << exportName << "\" for \"" + << this->GetName() << "\": is not valid."; + cmSystemTools::Error(e.str().c_str()); + return ""; + } + return exportName; + } + return this->GetName(); +} + +//---------------------------------------------------------------------------- void cmTarget::AppendBuildInterfaceIncludes() { if(this->GetType() != cmTarget::SHARED_LIBRARY && @@ -2806,17 +3167,45 @@ void cmTarget::InsertInclude(const cmValueWithOrigin &entry, { cmGeneratorExpression ge(entry.Backtrace); - std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::iterator position + std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position = before ? this->Internal->IncludeDirectoriesEntries.begin() : this->Internal->IncludeDirectoriesEntries.end(); this->Internal->IncludeDirectoriesEntries.insert(position, - new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value))); + new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value))); +} + +//---------------------------------------------------------------------------- +void cmTarget::InsertCompileOption(const cmValueWithOrigin &entry, + bool before) +{ + cmGeneratorExpression ge(entry.Backtrace); + + std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position + = before ? this->Internal->CompileOptionsEntries.begin() + : this->Internal->CompileOptionsEntries.end(); + + this->Internal->CompileOptionsEntries.insert(position, + new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value))); +} + +//---------------------------------------------------------------------------- +void cmTarget::InsertCompileDefinition(const cmValueWithOrigin &entry, + bool before) +{ + cmGeneratorExpression ge(entry.Backtrace); + + std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position + = before ? this->Internal->CompileDefinitionsEntries.begin() + : this->Internal->CompileDefinitionsEntries.end(); + + this->Internal->CompileDefinitionsEntries.insert(position, + new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value))); } //---------------------------------------------------------------------------- static void processIncludeDirectories(cmTarget *tgt, - const std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries, + const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, std::vector<std::string> &includes, std::set<std::string> &uniqueIncludes, cmGeneratorExpressionDAGChecker *dagChecker, @@ -2824,12 +3213,12 @@ static void processIncludeDirectories(cmTarget *tgt, { cmMakefile *mf = tgt->GetMakefile(); - for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator + for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator it = entries.begin(), end = entries.end(); it != end; ++it) { bool testIsOff = true; bool cacheIncludes = false; - std::vector<std::string> entryIncludes = (*it)->CachedIncludes; + std::vector<std::string> entryIncludes = (*it)->CachedEntries; if(!entryIncludes.empty()) { testIsOff = false; @@ -2876,15 +3265,45 @@ static void processIncludeDirectories(cmTarget *tgt, if (!cmSystemTools::FileIsFullPath(li->c_str())) { + cmOStringStream e; + bool noMessage = false; + cmake::MessageType messageType = cmake::FATAL_ERROR; if (!(*it)->TargetName.empty()) { - cmOStringStream e; e << "Target \"" << (*it)->TargetName << "\" contains relative " "path in its INTERFACE_INCLUDE_DIRECTORIES:\n" - " \"" << *li << "\" "; - tgt->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, - e.str().c_str()); - return; + " \"" << *li << "\""; + } + else + { + switch(tgt->GetPolicyStatusCMP0021()) + { + case cmPolicies::WARN: + { + cmOStringStream w; + e << (mf->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0021)) << "\n"; + messageType = cmake::AUTHOR_WARNING; + } + break; + case cmPolicies::OLD: + noMessage = true; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Issue the fatal message. + break; + } + e << "Found relative path while evaluating include directories of " + "\"" << tgt->GetName() << "\":\n \"" << *li << "\"\n"; + } + if (!noMessage) + { + tgt->GetMakefile()->IssueMessage(messageType, e.str().c_str()); + if (messageType == cmake::FATAL_ERROR) + { + return; + } } } @@ -2905,7 +3324,7 @@ static void processIncludeDirectories(cmTarget *tgt, } if (cacheIncludes) { - (*it)->CachedIncludes = entryIncludes; + (*it)->CachedEntries = entryIncludes; } if (!usedIncludes.empty()) { @@ -2925,8 +3344,8 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config) cmListFileBacktrace lfbt; cmGeneratorExpressionDAGChecker dagChecker(lfbt, - this->GetName(), - "INCLUDE_DIRECTORIES", 0, 0); + this->GetName(), + "INCLUDE_DIRECTORIES", 0, 0); this->AppendBuildInterfaceIncludes(); @@ -2961,8 +3380,8 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config) if (!this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString]) { for (std::vector<cmValueWithOrigin>::const_iterator - it = this->Internal->LinkInterfaceIncludeDirectoriesEntries.begin(), - end = this->Internal->LinkInterfaceIncludeDirectoriesEntries.end(); + it = this->Internal->LinkInterfacePropertyEntries.begin(), + end = this->Internal->LinkInterfacePropertyEntries.end(); it != end; ++it) { { @@ -2991,9 +3410,37 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config) this->Internal ->CachedLinkInterfaceIncludeDirectoriesEntries[configString].push_back( - new cmTargetInternals::IncludeDirectoriesEntry(cge, + new cmTargetInternals::TargetPropertyEntry(cge, it->Value)); } + + if(this->Makefile->IsOn("APPLE")) + { + LinkImplementation const* impl = this->GetLinkImplementation(config, + this); + for(std::vector<std::string>::const_iterator + it = impl->Libraries.begin(); + it != impl->Libraries.end(); ++it) + { + std::string libDir = cmSystemTools::CollapseFullPath(it->c_str()); + + static cmsys::RegularExpression + frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$"); + if(!frameworkCheck.find(libDir)) + { + continue; + } + + libDir = frameworkCheck.match(1); + + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(libDir.c_str()); + this->Internal + ->CachedLinkInterfaceIncludeDirectoriesEntries[configString] + .push_back(new cmTargetInternals::TargetPropertyEntry(cge)); + } + } } processIncludeDirectories(this, @@ -3019,90 +3466,294 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config) } //---------------------------------------------------------------------------- -std::string cmTarget::GetCompileDefinitions(const char *config) +static void processCompileOptionsInternal(cmTarget *tgt, + const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, + std::vector<std::string> &options, + std::set<std::string> &uniqueOptions, + cmGeneratorExpressionDAGChecker *dagChecker, + const char *config, bool debugOptions, const char *logName) { - const char *configProp = 0; - if (config) + cmMakefile *mf = tgt->GetMakefile(); + + for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator + it = entries.begin(), end = entries.end(); it != end; ++it) { - std::string configPropName; - configPropName = "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config); - configProp = this->GetProperty(configPropName.c_str()); + bool cacheOptions = false; + std::vector<std::string> entryOptions = (*it)->CachedEntries; + if(entryOptions.empty()) + { + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt, + dagChecker), + entryOptions); + if (mf->IsGeneratingBuildSystem() + && !(*it)->ge->GetHadContextSensitiveCondition()) + { + cacheOptions = true; + } + } + std::string usedOptions; + for(std::vector<std::string>::iterator + li = entryOptions.begin(); li != entryOptions.end(); ++li) + { + std::string opt = *li; + + if(uniqueOptions.insert(opt).second) + { + options.push_back(opt); + if (debugOptions) + { + usedOptions += " * " + opt + "\n"; + } + } + } + if (cacheOptions) + { + (*it)->CachedEntries = entryOptions; + } + if (!usedOptions.empty()) + { + mf->GetCMakeInstance()->IssueMessage(cmake::LOG, + std::string("Used compile ") + logName + + std::string(" for target ") + + tgt->GetName() + ":\n" + + usedOptions, (*it)->ge->GetBacktrace()); + } } +} + +//---------------------------------------------------------------------------- +static void processCompileOptions(cmTarget *tgt, + const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, + std::vector<std::string> &options, + std::set<std::string> &uniqueOptions, + cmGeneratorExpressionDAGChecker *dagChecker, + const char *config, bool debugOptions) +{ + processCompileOptionsInternal(tgt, entries, options, uniqueOptions, + dagChecker, config, debugOptions, "options"); +} - const char *noconfigProp = this->GetProperty("COMPILE_DEFINITIONS"); +//---------------------------------------------------------------------------- +void cmTarget::GetCompileOptions(std::vector<std::string> &result, + const char *config) +{ + std::set<std::string> uniqueOptions; cmListFileBacktrace lfbt; + cmGeneratorExpressionDAGChecker dagChecker(lfbt, - this->GetName(), - "COMPILE_DEFINITIONS", 0, 0); + this->GetName(), + "COMPILE_OPTIONS", 0, 0); - std::string defsString = (noconfigProp ? noconfigProp : ""); - if (configProp && noconfigProp) + std::vector<std::string> debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) { - defsString += ";"; + cmSystemTools::ExpandListArgument(debugProp, debugProperties); } - defsString += (configProp ? configProp : ""); - cmGeneratorExpression ge(lfbt); - std::string result = ge.Parse(defsString.c_str())->Evaluate(this->Makefile, - config, - false, - this, - &dagChecker); - - std::vector<std::string> libs; - this->GetDirectLinkLibraries(config, libs, this); + bool debugOptions = !this->DebugCompileOptionsDone + && std::find(debugProperties.begin(), + debugProperties.end(), + "COMPILE_OPTIONS") + != debugProperties.end(); - if (libs.empty()) + if (this->Makefile->IsGeneratingBuildSystem()) { - return result; + this->DebugCompileOptionsDone = true; } - std::string sep; - std::string depString; - for (std::vector<std::string>::const_iterator it = libs.begin(); - it != libs.end(); ++it) + processCompileOptions(this, + this->Internal->CompileOptionsEntries, + result, + uniqueOptions, + &dagChecker, + config, + debugOptions); + + std::string configString = config ? config : ""; + if (!this->Internal->CacheLinkInterfaceCompileOptionsDone[configString]) { - if ((cmGeneratorExpression::IsValidTargetName(it->c_str()) - || cmGeneratorExpression::Find(it->c_str()) != std::string::npos) - && this->Makefile->FindTargetToUse(it->c_str())) + for (std::vector<cmValueWithOrigin>::const_iterator + it = this->Internal->LinkInterfacePropertyEntries.begin(), + end = this->Internal->LinkInterfacePropertyEntries.end(); + it != end; ++it) { - depString += sep + "$<TARGET_PROPERTY:" - + *it + ",INTERFACE_COMPILE_DEFINITIONS>"; - sep = ";"; + { + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(it->Value); + std::string targetResult = cge->Evaluate(this->Makefile, config, + false, this, 0, 0); + if (!this->Makefile->FindTargetToUse(targetResult.c_str())) + { + continue; + } + } + std::string optionGenex = "$<TARGET_PROPERTY:" + + it->Value + ",INTERFACE_COMPILE_OPTIONS>"; + if (cmGeneratorExpression::Find(it->Value) != std::string::npos) + { + // Because it->Value is a generator expression, ensure that it + // evaluates to the non-empty string before being used in the + // TARGET_PROPERTY expression. + optionGenex = "$<$<BOOL:" + it->Value + ">:" + optionGenex + ">"; + } + cmGeneratorExpression ge(it->Backtrace); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse( + optionGenex); + + this->Internal + ->CachedLinkInterfaceCompileOptionsEntries[configString].push_back( + new cmTargetInternals::TargetPropertyEntry(cge, + it->Value)); } } - std::string configString = config ? config : ""; - if (!this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString]) + processCompileOptions(this, + this->Internal->CachedLinkInterfaceCompileOptionsEntries[configString], + result, + uniqueOptions, + &dagChecker, + config, + debugOptions); + + if (!this->Makefile->IsGeneratingBuildSystem()) + { + deleteAndClear(this->Internal->CachedLinkInterfaceCompileOptionsEntries); + } + else + { + this->Internal->CacheLinkInterfaceCompileOptionsDone[configString] = true; + } +} + +//---------------------------------------------------------------------------- +static void processCompileDefinitions(cmTarget *tgt, + const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, + std::vector<std::string> &options, + std::set<std::string> &uniqueOptions, + cmGeneratorExpressionDAGChecker *dagChecker, + const char *config, bool debugOptions) +{ + processCompileOptionsInternal(tgt, entries, options, uniqueOptions, + dagChecker, config, debugOptions, + "definitions"); +} + +//---------------------------------------------------------------------------- +void cmTarget::GetCompileDefinitions(std::vector<std::string> &list, + const char *config) +{ + std::set<std::string> uniqueOptions; + cmListFileBacktrace lfbt; + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "COMPILE_DEFINITIONS", 0, 0); + + std::vector<std::string> debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) { - cmGeneratorExpression ge2(lfbt); - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge2 = - ge2.Parse(depString); - this->Internal->CachedLinkInterfaceCompileDefinitions[configString] = - cge2->Evaluate(this->Makefile, - config, - false, - this, - &dagChecker); + cmSystemTools::ExpandListArgument(debugProp, debugProperties); } - if (!this->Internal->CachedLinkInterfaceCompileDefinitions[configString] - .empty()) + + bool debugDefines = !this->DebugCompileDefinitionsDone + && std::find(debugProperties.begin(), + debugProperties.end(), + "COMPILE_DEFINITIONS") + != debugProperties.end(); + + if (this->Makefile->IsGeneratingBuildSystem()) + { + this->DebugCompileDefinitionsDone = true; + } + + processCompileDefinitions(this, + this->Internal->CompileDefinitionsEntries, + list, + uniqueOptions, + &dagChecker, + config, + debugDefines); + + std::string configString = config ? config : ""; + if (!this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString]) { - result += (result.empty() ? "" : ";") - + this->Internal->CachedLinkInterfaceCompileDefinitions[configString]; + for (std::vector<cmValueWithOrigin>::const_iterator + it = this->Internal->LinkInterfacePropertyEntries.begin(), + end = this->Internal->LinkInterfacePropertyEntries.end(); + it != end; ++it) + { + { + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(it->Value); + std::string targetResult = cge->Evaluate(this->Makefile, config, + false, this, 0, 0); + if (!this->Makefile->FindTargetToUse(targetResult.c_str())) + { + continue; + } + } + std::string defsGenex = "$<TARGET_PROPERTY:" + + it->Value + ",INTERFACE_COMPILE_DEFINITIONS>"; + if (cmGeneratorExpression::Find(it->Value) != std::string::npos) + { + // Because it->Value is a generator expression, ensure that it + // evaluates to the non-empty string before being used in the + // TARGET_PROPERTY expression. + defsGenex = "$<$<BOOL:" + it->Value + ">:" + defsGenex + ">"; + } + cmGeneratorExpression ge(it->Backtrace); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse( + defsGenex); + + this->Internal + ->CachedLinkInterfaceCompileDefinitionsEntries[configString].push_back( + new cmTargetInternals::TargetPropertyEntry(cge, + it->Value)); + } + if (config) + { + std::string configPropName = "COMPILE_DEFINITIONS_" + + cmSystemTools::UpperCase(config); + const char *configProp = this->GetProperty(configPropName.c_str()); + std::string defsString = (configProp ? configProp : ""); + + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(defsString); + this->Internal + ->CachedLinkInterfaceCompileDefinitionsEntries[configString].push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); + } + } + processCompileDefinitions(this, + this->Internal->CachedLinkInterfaceCompileDefinitionsEntries[configString], + list, + uniqueOptions, + &dagChecker, + config, + debugDefines); + if (!this->Makefile->IsGeneratingBuildSystem()) { - this->Internal->CachedLinkInterfaceCompileDefinitions[configString] = ""; + deleteAndClear(this->Internal + ->CachedLinkInterfaceCompileDefinitionsEntries); } else { this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString] = true; } - - return result; } //---------------------------------------------------------------------------- @@ -3163,6 +3814,29 @@ static void cmTargetCheckLINK_INTERFACE_LIBRARIES( } //---------------------------------------------------------------------------- +static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, + cmMakefile* context) +{ + // Look for link-type keywords in the value. + static cmsys::RegularExpression + keys("(^|;)(debug|optimized|general)(;|$)"); + if(!keys.find(value)) + { + return; + } + + // Report an error. + cmOStringStream e; + + e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type " + "keyword \"" << keys.match(2) << "\". The INTERFACE_LINK_LIBRARIES " + "property may contain configuration-sensitive generator-expressions " + "which may be used to specify per-configuration rules."; + + context->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- void cmTarget::CheckProperty(const char* prop, cmMakefile* context) { // Certain properties need checking. @@ -3180,6 +3854,13 @@ void cmTarget::CheckProperty(const char* prop, cmMakefile* context) cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true); } } + if(strncmp(prop, "INTERFACE_LINK_LIBRARIES", 24) == 0) + { + if(const char* value = this->GetProperty(prop)) + { + cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context); + } + } } //---------------------------------------------------------------------------- @@ -3304,17 +3985,23 @@ const char* cmTarget::NormalGetLocation(const char* config) // Now handle the deprecated build-time configuration location. this->Location = this->GetDirectory(); - if(!this->Location.empty()) - { - this->Location += "/"; - } const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); if(cfgid && strcmp(cfgid, ".") != 0) { - this->Location += cfgid; this->Location += "/"; + this->Location += cfgid; } - this->Location = this->BuildMacContentDirectory(this->Location, config); + + if(this->IsAppBundleOnApple()) + { + std::string macdir = this->BuildMacContentDirectory("", config, false); + if(!macdir.empty()) + { + this->Location += "/"; + this->Location += macdir; + } + } + this->Location += "/"; this->Location += this->GetFullName(config, false); return this->Location.c_str(); } @@ -3390,6 +4077,11 @@ const char *cmTarget::GetProperty(const char* prop, return 0; } + if (strcmp(prop, "NAME") == 0) + { + return this->GetName(); + } + // Watch for special "computed" properties that are dependent on // other properties or variables. Always recompute them. if(this->GetType() == cmTarget::EXECUTABLE || @@ -3437,9 +4129,9 @@ const char *cmTarget::GetProperty(const char* prop, static std::string output; output = ""; std::string sep; - typedef cmTargetInternals::IncludeDirectoriesEntry - IncludeDirectoriesEntry; - for (std::vector<IncludeDirectoriesEntry*>::const_iterator + typedef cmTargetInternals::TargetPropertyEntry + TargetPropertyEntry; + for (std::vector<TargetPropertyEntry*>::const_iterator it = this->Internal->IncludeDirectoriesEntries.begin(), end = this->Internal->IncludeDirectoriesEntries.end(); it != end; ++it) @@ -3450,6 +4142,42 @@ const char *cmTarget::GetProperty(const char* prop, } return output.c_str(); } + if(strcmp(prop,"COMPILE_OPTIONS") == 0) + { + static std::string output; + output = ""; + std::string sep; + typedef cmTargetInternals::TargetPropertyEntry + TargetPropertyEntry; + for (std::vector<TargetPropertyEntry*>::const_iterator + it = this->Internal->CompileOptionsEntries.begin(), + end = this->Internal->CompileOptionsEntries.end(); + it != end; ++it) + { + output += sep; + output += (*it)->ge->GetInput(); + sep = ";"; + } + return output.c_str(); + } + if(strcmp(prop,"COMPILE_DEFINITIONS") == 0) + { + static std::string output; + output = ""; + std::string sep; + typedef cmTargetInternals::TargetPropertyEntry + TargetPropertyEntry; + for (std::vector<TargetPropertyEntry*>::const_iterator + it = this->Internal->CompileDefinitionsEntries.begin(), + end = this->Internal->CompileDefinitionsEntries.end(); + it != end; ++it) + { + output += sep; + output += (*it)->ge->GetInput(); + sep = ";"; + } + return output.c_str(); + } if (strcmp(prop,"IMPORTED") == 0) { @@ -3798,6 +4526,10 @@ std::string cmTarget::GetSOName(const char* config) else { // Use the soname given if any. + if(info->SOName.find("@rpath/") == 0) + { + return info->SOName.substr(6); + } return info->SOName; } } @@ -3820,6 +4552,79 @@ std::string cmTarget::GetSOName(const char* config) } //---------------------------------------------------------------------------- +bool cmTarget::HasMacOSXRpath(const char* config) +{ + bool install_name_is_rpath = false; + bool macosx_rpath = this->GetPropertyAsBool("MACOSX_RPATH"); + + if(!this->IsImportedTarget) + { + const char* install_name = this->GetProperty("INSTALL_NAME_DIR"); + bool use_install_name = + this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"); + if(install_name && use_install_name && + std::string(install_name) == "@rpath") + { + install_name_is_rpath = true; + } + else if(install_name && use_install_name) + { + return false; + } + } + else + { + // Lookup the imported soname. + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this)) + { + if(!info->NoSOName && !info->SOName.empty()) + { + if(info->SOName.find("@rpath/") == 0) + { + install_name_is_rpath = true; + } + } + else + { + std::string install_name; + cmSystemTools::GuessLibraryInstallName(info->Location, install_name); + if(install_name.find("@rpath") != std::string::npos) + { + install_name_is_rpath = true; + } + } + } + } + + if(!install_name_is_rpath && !macosx_rpath) + { + return false; + } + + if(!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG")) + { + cmOStringStream w; + w << "Attempting to use"; + if(macosx_rpath) + { + w << " MACOSX_RPATH"; + } + else + { + w << " @rpath"; + } + w << " without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being set."; + w << " This could be because you are using a Mac OS X version"; + w << " less than 10.5 or because CMake's platform configuration is"; + w << " corrupt."; + cmake* cm = this->Makefile->GetCMakeInstance(); + cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace()); + } + + return true; +} + +//---------------------------------------------------------------------------- bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config) { if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY) @@ -3916,7 +4721,13 @@ std::string cmTarget::GetFullPath(const char* config, bool implib, std::string cmTarget::NormalGetFullPath(const char* config, bool implib, bool realname) { - std::string fpath = this->GetMacContentDirectory(config, implib); + std::string fpath = this->GetDirectory(config, implib); + fpath += "/"; + if(this->IsAppBundleOnApple()) + { + fpath = this->BuildMacContentDirectory(fpath, config, false); + fpath += "/"; + } // Add the full name of the target. if(implib) @@ -4048,10 +4859,28 @@ void cmTarget::GetFullNameInternal(const char* config, targetSuffix = this->Makefile->GetSafeDefinition(suffixVar); } - // frameworks do not have a prefix or a suffix + // frameworks have directory prefix but no suffix + std::string fw_prefix; if(this->IsFrameworkOnApple()) { - targetPrefix = 0; + fw_prefix = this->GetOutputName(config, false); + fw_prefix += ".framework/"; + targetPrefix = fw_prefix.c_str(); + targetSuffix = 0; + } + + if(this->IsCFBundleOnApple()) + { + fw_prefix = this->GetOutputName(config, false); + fw_prefix += "."; + const char *ext = this->GetProperty("BUNDLE_EXTENSION"); + if (!ext) + { + ext = "bundle"; + } + fw_prefix += ext; + fw_prefix += "/Contents/MacOS/"; + targetPrefix = fw_prefix.c_str(); targetSuffix = 0; } @@ -4131,13 +4960,24 @@ void cmTarget::GetLibraryNames(std::string& name, // The library name. name = prefix+base+suffix; - // The library's soname. - this->ComputeVersionedName(soName, prefix, base, suffix, - name, soversion); - - // The library's real name on disk. - this->ComputeVersionedName(realName, prefix, base, suffix, - name, version); + if(this->IsFrameworkOnApple()) + { + realName = prefix; + realName += "Versions/"; + realName += this->GetFrameworkVersion(); + realName += "/"; + realName += base; + soName = realName; + } + else + { + // The library's soname. + this->ComputeVersionedName(soName, prefix, base, suffix, + name, soversion); + // The library's real name on disk. + this->ComputeVersionedName(realName, prefix, base, suffix, + name, version); + } // The import library name. if(this->GetType() == cmTarget::SHARED_LIBRARY || @@ -4425,14 +5265,13 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config) } //---------------------------------------------------------------------------- -std::string cmTarget::GetInstallNameDirForBuildTree(const char* config, - bool for_xcode) +std::string cmTarget::GetInstallNameDirForBuildTree(const char* config) { // If building directly for installation then the build tree install_name // is the same as the install tree. if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) { - return GetInstallNameDirForInstallTree(config, for_xcode); + return GetInstallNameDirForInstallTree(); } // Use the build tree directory for the target. @@ -4440,12 +5279,16 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config, !this->Makefile->IsOn("CMAKE_SKIP_RPATH") && !this->GetPropertyAsBool("SKIP_BUILD_RPATH")) { - std::string dir = this->GetDirectory(config); - dir += "/"; - if(this->IsFrameworkOnApple() && !for_xcode) + std::string dir; + if(this->GetPropertyAsBool("MACOSX_RPATH")) + { + dir = "@rpath"; + } + else { - dir += this->GetFrameworkDirectory(config); + dir = this->GetDirectory(config); } + dir += "/"; return dir; } else @@ -4455,29 +5298,26 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config, } //---------------------------------------------------------------------------- -std::string cmTarget::GetInstallNameDirForInstallTree(const char* config, - bool for_xcode) +std::string cmTarget::GetInstallNameDirForInstallTree() { if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { std::string dir; + const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); if(!this->Makefile->IsOn("CMAKE_SKIP_RPATH") && !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH")) { - const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); if(install_name_dir && *install_name_dir) { dir = install_name_dir; dir += "/"; } } - - if(this->IsFrameworkOnApple() && !for_xcode) + if(!install_name_dir && this->GetPropertyAsBool("MACOSX_RPATH")) { - dir += this->GetFrameworkDirectory(config); + dir = "@rpath/"; } - return dir; } else @@ -5059,7 +5899,6 @@ void cmTarget::GetLanguages(std::set<cmStdString>& languages) const //---------------------------------------------------------------------------- bool cmTarget::IsChrpathUsed(const char* config) { -#if defined(CMAKE_USE_ELF_PARSER) // Only certain target types have an rpath. if(!(this->GetType() == cmTarget::SHARED_LIBRARY || this->GetType() == cmTarget::MODULE_LIBRARY || @@ -5093,6 +5932,12 @@ bool cmTarget::IsChrpathUsed(const char* config) return false; } + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + return true; + } + +#if defined(CMAKE_USE_ELF_PARSER) // Enable if the rpath flag uses a separator and the target uses ELF // binaries. if(const char* ll = this->GetLinkerLanguage(config, this)) @@ -5289,7 +6134,6 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, ImportInfo& info, cmTarget *headTarget) { - (void)headTarget; // This method finds information about an imported target from its // properties. The "IMPORTED_" namespace is reserved for properties // defined by the project exporting the target. @@ -5379,11 +6223,16 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, // Get the link interface. { - std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; - linkProp += suffix; - + std::string linkProp = "INTERFACE_LINK_LIBRARIES"; const char *propertyLibs = this->GetProperty(linkProp.c_str()); + if (!propertyLibs) + { + linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; + linkProp += suffix; + propertyLibs = this->GetProperty(linkProp.c_str()); + } + if(!propertyLibs) { linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; @@ -5425,7 +6274,7 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, } // Get the link languages. - if(this->GetType() == cmTarget::STATIC_LIBRARY) + if(this->LinkLanguagePropagatesToDependents()) { std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES"; linkProp += suffix; @@ -5501,6 +6350,48 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config, } //---------------------------------------------------------------------------- +void cmTarget::GetTransitivePropertyLinkLibraries( + const char* config, + cmTarget *headTarget, + std::vector<std::string> &libs) +{ + cmTarget::LinkInterface const* iface = this->GetLinkInterface(config, + headTarget); + if (!iface) + { + return; + } + if(this->GetType() != STATIC_LIBRARY + || this->GetPolicyStatusCMP0022() == cmPolicies::WARN + || this->GetPolicyStatusCMP0022() == cmPolicies::OLD) + { + libs = iface->Libraries; + return; + } + + const char* linkIfaceProp = "INTERFACE_LINK_LIBRARIES"; + const char* interfaceLibs = this->GetProperty(linkIfaceProp); + + if (!interfaceLibs) + { + return; + } + + // The interface libraries have been explicitly set. + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(), + linkIfaceProp, 0, 0); + dagChecker.SetTransitivePropertiesOnly(); + cmSystemTools::ExpandListArgument(ge.Parse(interfaceLibs)->Evaluate( + this->Makefile, + config, + false, + headTarget, + this, &dagChecker), libs); +} + +//---------------------------------------------------------------------------- bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, cmTarget *headTarget) { @@ -5519,9 +6410,19 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, // libraries and executables that export symbols. const char* explicitLibraries = 0; std::string linkIfaceProp; - if(this->GetType() == cmTarget::SHARED_LIBRARY || - this->IsExecutableWithExports()) + if(this->PolicyStatusCMP0022 != cmPolicies::OLD && + this->PolicyStatusCMP0022 != cmPolicies::WARN) + { + // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES. + linkIfaceProp = "INTERFACE_LINK_LIBRARIES"; + explicitLibraries = this->GetProperty(linkIfaceProp.c_str()); + } + else if(this->GetType() == cmTarget::SHARED_LIBRARY || + this->IsExecutableWithExports()) { + // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a + // shared lib or executable. + // Lookup the per-configuration property. linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; linkIfaceProp += suffix; @@ -5535,6 +6436,33 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, } } + if(explicitLibraries && this->PolicyStatusCMP0022 == cmPolicies::WARN && + !this->Internal->PolicyWarnedCMP0022) + { + // Compare the explicitly set old link interface properties to the + // preferred new link interface property one and warn if different. + const char* newExplicitLibraries = + this->GetProperty("INTERFACE_LINK_LIBRARIES"); + if (newExplicitLibraries + && strcmp(newExplicitLibraries, explicitLibraries) != 0) + { + cmOStringStream w; + w << + (this->Makefile->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n" + "Target \"" << this->GetName() << "\" has an " + "INTERFACE_LINK_LIBRARIES property which differs from its " << + linkIfaceProp << " properties." + "\n" + "INTERFACE_LINK_LIBRARIES:\n" + " " << newExplicitLibraries << "\n" << + linkIfaceProp << ":\n" + " " << (explicitLibraries ? explicitLibraries : "(empty)") << "\n"; + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Internal->PolicyWarnedCMP0022 = true; + } + } + // There is no implicit link interface for executables or modules // so if none was explicitly set then there is no link interface. // Note that CMake versions 2.2 and below allowed linking to modules. @@ -5560,7 +6488,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, headTarget, this, &dagChecker), iface.Libraries); - if(this->GetType() == cmTarget::SHARED_LIBRARY) + if(this->GetType() == cmTarget::SHARED_LIBRARY + || this->GetType() == cmTarget::STATIC_LIBRARY) { // Shared libraries may have runtime implementation dependencies // on other shared libraries that are not in the interface. @@ -5594,9 +6523,19 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, } } } + if(this->LinkLanguagePropagatesToDependents()) + { + // Targets using this archive need its language runtime libraries. + iface.Languages = impl->Languages; + } } } - else + else if (this->PolicyStatusCMP0022 == cmPolicies::WARN + || this->PolicyStatusCMP0022 == cmPolicies::OLD) + // If CMP0022 is NEW then the plain tll signature sets the + // INTERFACE_LINK_LIBRARIES, so if we get here then the project + // cleared the property explicitly and we should not fall back + // to the link implementation. { // The link implementation is the default link interface. LinkImplementation const* impl = this->GetLinkImplementation(config, @@ -5604,11 +6543,75 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, iface.ImplementationIsInterface = true; iface.Libraries = impl->Libraries; iface.WrongConfigLibraries = impl->WrongConfigLibraries; - if(this->GetType() == cmTarget::STATIC_LIBRARY) + if(this->LinkLanguagePropagatesToDependents()) { // Targets using this archive need its language runtime libraries. iface.Languages = impl->Languages; } + + if(this->PolicyStatusCMP0022 == cmPolicies::WARN && + !this->Internal->PolicyWarnedCMP0022) + { + // Compare the link implementation fallback link interface to the + // preferred new link interface property and warn if different. + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(), + "INTERFACE_LINK_LIBRARIES", 0, 0); + std::vector<std::string> ifaceLibs; + const char* newExplicitLibraries = + this->GetProperty("INTERFACE_LINK_LIBRARIES"); + cmSystemTools::ExpandListArgument( + ge.Parse(newExplicitLibraries)->Evaluate(this->Makefile, + config, + false, + headTarget, + this, &dagChecker), + ifaceLibs); + if (ifaceLibs != impl->Libraries) + { + std::string oldLibraries; + std::string newLibraries; + const char *sep = ""; + for(std::vector<std::string>::const_iterator it + = impl->Libraries.begin(); it != impl->Libraries.end(); ++it) + { + oldLibraries += sep; + oldLibraries += *it; + sep = ";"; + } + sep = ""; + for(std::vector<std::string>::const_iterator it + = ifaceLibs.begin(); it != ifaceLibs.end(); ++it) + { + newLibraries += sep; + newLibraries += *it; + sep = ";"; + } + if(oldLibraries.empty()) + { oldLibraries = "(empty)"; } + if(newLibraries.empty()) + { newLibraries = "(empty)"; } + + cmOStringStream w; + w << + (this->Makefile->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n" + "Target \"" << this->GetName() << "\" has an " + "INTERFACE_LINK_LIBRARIES property. " + "This should be preferred as the source of the link interface " + "for this library but because CMP0022 is not set CMake is " + "ignoring the property and using the link implementation " + "as the link interface instead." + "\n" + "INTERFACE_LINK_LIBRARIES:\n" + " " << newLibraries << "\n" + "Link implementation:\n" + " " << oldLibraries << "\n"; + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + this->Internal->PolicyWarnedCMP0022 = true; + } + } } if(this->GetType() == cmTarget::STATIC_LIBRARY) @@ -5936,59 +6939,86 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head) } //---------------------------------------------------------------------------- -std::string cmTarget::GetFrameworkDirectory(const char* config) +std::string cmTarget::GetFrameworkDirectory(const char* config, + bool rootDir) { std::string fpath; - fpath += this->GetFullName(config, false); - fpath += ".framework/Versions/"; - fpath += this->GetFrameworkVersion(); - fpath += "/"; + fpath += this->GetOutputName(config, false); + fpath += ".framework"; + if(!rootDir) + { + fpath += "/Versions/"; + fpath += this->GetFrameworkVersion(); + } + return fpath; +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetCFBundleDirectory(const char* config, + bool contentOnly) +{ + std::string fpath; + fpath += this->GetOutputName(config, false); + fpath += "."; + const char *ext = this->GetProperty("BUNDLE_EXTENSION"); + if (!ext) + { + ext = "bundle"; + } + fpath += ext; + fpath += "/Contents"; + if(!contentOnly) + fpath += "/MacOS"; + return fpath; +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetAppBundleDirectory(const char* config, + bool contentOnly) +{ + std::string fpath = this->GetFullName(config, false); + fpath += ".app/Contents"; + if(!contentOnly) + fpath += "/MacOS"; return fpath; } //---------------------------------------------------------------------------- std::string cmTarget::BuildMacContentDirectory(const std::string& base, const char* config, - bool includeMacOS) + bool contentOnly) { std::string fpath = base; if(this->IsAppBundleOnApple()) { - fpath += this->GetFullName(config, false); - fpath += ".app/Contents/"; - if(includeMacOS) - fpath += "MacOS/"; + fpath += this->GetAppBundleDirectory(config, contentOnly); } if(this->IsFrameworkOnApple()) { - fpath += this->GetFrameworkDirectory(config); + fpath += this->GetFrameworkDirectory(config, contentOnly); } if(this->IsCFBundleOnApple()) { - fpath += this->GetFullName(config, false); - fpath += "."; - const char *ext = this->GetProperty("BUNDLE_EXTENSION"); - if (!ext) - { - ext = "bundle"; - } - fpath += ext; - fpath += "/Contents/"; - if(includeMacOS) - fpath += "MacOS/"; + fpath += this->GetCFBundleDirectory(config, contentOnly); } return fpath; } //---------------------------------------------------------------------------- std::string cmTarget::GetMacContentDirectory(const char* config, - bool implib, - bool includeMacOS) + bool implib) { // Start with the output directory for the target. std::string fpath = this->GetDirectory(config, implib); fpath += "/"; - fpath = this->BuildMacContentDirectory(fpath, config, includeMacOS); + bool contentOnly = true; + if(this->IsFrameworkOnApple()) + { + // additional files with a framework go into the version specific + // directory + contentOnly = false; + } + fpath = this->BuildMacContentDirectory(fpath, config, contentOnly); return fpath; } @@ -6035,6 +7065,8 @@ cmTargetInternalPointer cmTargetInternalPointer::~cmTargetInternalPointer() { deleteAndClear(this->Pointer->IncludeDirectoriesEntries); + deleteAndClear(this->Pointer->CompileOptionsEntries); + deleteAndClear(this->Pointer->CompileDefinitionsEntries); delete this->Pointer; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 9d467961b..27b74ca4b 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -19,6 +19,14 @@ #include <cmsys/auto_ptr.hxx> +#define CM_FOR_EACH_TARGET_POLICY(F) \ + F(CMP0003) \ + F(CMP0004) \ + F(CMP0008) \ + F(CMP0020) \ + F(CMP0021) \ + F(CMP0022) + class cmake; class cmMakefile; class cmSourceFile; @@ -85,26 +93,19 @@ public: ///! Set/Get the name of the target const char* GetName() const {return this->Name.c_str();} + const char* GetExportName(); ///! Set the cmMakefile that owns this target void SetMakefile(cmMakefile *mf); cmMakefile *GetMakefile() const { return this->Makefile;}; - /** Get the status of policy CMP0003 when the target was created. */ - cmPolicies::PolicyStatus GetPolicyStatusCMP0003() const - { return this->PolicyStatusCMP0003; } - - /** Get the status of policy CMP0004 when the target was created. */ - cmPolicies::PolicyStatus GetPolicyStatusCMP0004() const - { return this->PolicyStatusCMP0004; } +#define DECLARE_TARGET_POLICY(POLICY) \ + cmPolicies::PolicyStatus GetPolicyStatus ## POLICY () const \ + { return this->PolicyStatus ## POLICY; } - /** Get the status of policy CMP0008 when the target was created. */ - cmPolicies::PolicyStatus GetPolicyStatusCMP0008() const - { return this->PolicyStatusCMP0008; } + CM_FOR_EACH_TARGET_POLICY(DECLARE_TARGET_POLICY) - /** Get the status of policy CMP0020 when the target was created. */ - cmPolicies::PolicyStatus GetPolicyStatusCMP0020() const - { return this->PolicyStatusCMP0020; } +#undef DECLARE_TARGET_POLICY /** * Get the list of the custom commands for this target @@ -189,6 +190,12 @@ public: void AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, LinkLibraryType llt); + enum TLLSignature { + KeywordTLLSignature, + PlainTLLSignature + }; + bool PushTLLCommandTrace(TLLSignature signature); + void GetTllSignatureTraces(cmOStringStream &s, TLLSignature sig) const; void MergeLinkLibraries( cmMakefile& mf, const char* selfname, const LinkLibraryVectorType& libs ); @@ -271,6 +278,9 @@ public: if the target cannot be linked. */ LinkInterface const* GetLinkInterface(const char* config, cmTarget *headTarget); + void GetTransitivePropertyLinkLibraries(const char* config, + cmTarget *headTarget, + std::vector<std::string> &libs); /** The link implementation specifies the direct library dependencies needed by the object files of the target. */ @@ -336,7 +346,7 @@ public: * Trace through the source files in this target and add al source files * that they depend on, used by all generators */ - void TraceDependencies(const char* vsProjectFile); + void TraceDependencies(); /** * Make sure the full path to all source files is known. @@ -362,6 +372,9 @@ public: /** Get the soname of the target. Allowed only for a shared library. */ std::string GetSOName(const char* config); + /** Whether this library has @rpath and platform supports it. */ + bool HasMacOSXRpath(const char* config); + /** Test for special case of a third-party shared library that has no soname at all. */ bool IsImportedSharedLibWithoutSOName(const char* config); @@ -407,10 +420,14 @@ public: /** Return true if builtin chrpath will work for this target */ bool IsChrpathUsed(const char* config); - std::string GetInstallNameDirForBuildTree(const char* config, - bool for_xcode = false); - std::string GetInstallNameDirForInstallTree(const char* config, - bool for_xcode = false); + /** Return the install name directory for the target in the + * build tree. For example: "@rpath/", "@loader_path/", + * or "/full/path/to/library". */ + std::string GetInstallNameDirForBuildTree(const char* config); + + /** Return the install name directory for the target in the + * install tree. For example: "@rpath/" or "@loader_path/". */ + std::string GetInstallNameDirForInstallTree(); cmComputeLinkInformation* GetLinkInformation(const char* config, cmTarget *head = 0); @@ -430,7 +447,8 @@ public: If no macro should be defined null is returned. */ const char* GetExportMacro(); - std::string GetCompileDefinitions(const char *config); + void GetCompileDefinitions(std::vector<std::string> &result, + const char *config); // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change @@ -462,6 +480,10 @@ public: /** Return whether this target is an executable Bundle on Apple. */ bool IsAppBundleOnApple(); + /** Return whether this target is an executable Bundle, a framework + or CFBundle on Apple. */ + bool IsBundleOnApple(); + /** Return the framework version string. Undefined if IsFrameworkOnApple returns false. */ std::string GetFrameworkVersion(); @@ -476,28 +498,35 @@ public: directory. */ bool UsesDefaultOutputDir(const char* config, bool implib); - /** Append to @a base the mac content directory and return it. */ - std::string BuildMacContentDirectory(const std::string& base, - const char* config = 0, - bool includeMacOS = true); - /** @return the mac content directory for this target. */ - std::string GetMacContentDirectory(const char* config = 0, - bool implib = false, - bool includeMacOS = true); + std::string GetMacContentDirectory(const char* config, + bool implib); /** @return whether this target have a well defined output file name. */ bool HaveWellDefinedOutputFiles(); /** @return the Mac framework directory without the base. */ - std::string GetFrameworkDirectory(const char* config = 0); + std::string GetFrameworkDirectory(const char* config, bool rootDir); + + /** @return the Mac CFBundle directory without the base */ + std::string GetCFBundleDirectory(const char* config, bool contentOnly); + + /** @return the Mac App directory without the base */ + std::string GetAppBundleDirectory(const char* config, bool contentOnly); std::vector<std::string> GetIncludeDirectories(const char *config); void InsertInclude(const cmValueWithOrigin &entry, bool before = false); + void InsertCompileOption(const cmValueWithOrigin &entry, + bool before = false); + void InsertCompileDefinition(const cmValueWithOrigin &entry, + bool before = false); void AppendBuildInterfaceIncludes(); + void GetCompileOptions(std::vector<std::string> &result, + const char *config); + bool IsNullImpliedByLinkLibraries(const std::string &p); bool IsLinkInterfaceDependentBoolProperty(const std::string &p, const char *config); @@ -512,7 +541,24 @@ public: std::string GetDebugGeneratorExpressions(const std::string &value, cmTarget::LinkLibraryType llt); + + void AddSystemIncludeDirectories(const std::set<cmStdString> &incs); + void AddSystemIncludeDirectories(const std::vector<std::string> &incs); + std::set<cmStdString> const & GetSystemIncludeDirectories() const + { return this->SystemIncludeDirectories; } + + void FinalizeSystemIncludeDirectories(); + + bool LinkLanguagePropagatesToDependents() const + { return this->TargetTypeValue == STATIC_LIBRARY; } + private: + // The set of include directories that are marked as system include + // directories. + std::set<cmStdString> SystemIncludeDirectories; + + std::vector<std::pair<TLLSignature, cmListFileBacktrace> > TLLCommands; + /** * A list of direct dependencies. Use in conjunction with DependencyMap. */ @@ -596,6 +642,11 @@ private: the same as GetFullName. */ std::string NormalGetRealName(const char* config); + /** Append to @a base the mac content directory and return it. */ + std::string BuildMacContentDirectory(const std::string& base, + const char* config, + bool contentOnly); + private: std::string Name; std::vector<cmCustomCommand> PreBuildCommands; @@ -622,6 +673,8 @@ private: bool IsApple; bool IsImportedTarget; bool DebugIncludesDone; + bool DebugCompileOptionsDone; + bool DebugCompileDefinitionsDone; mutable std::set<std::string> LinkImplicitNullProperties; bool BuildInterfaceIncludesAppended; @@ -660,10 +713,12 @@ private: cmMakefile* Makefile; // Policy status recorded when target was created. - cmPolicies::PolicyStatus PolicyStatusCMP0003; - cmPolicies::PolicyStatus PolicyStatusCMP0004; - cmPolicies::PolicyStatus PolicyStatusCMP0008; - cmPolicies::PolicyStatus PolicyStatusCMP0020; +#define TARGET_POLICY_MEMBER(POLICY) \ + cmPolicies::PolicyStatus PolicyStatus ## POLICY; + + CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_MEMBER) + +#undef TARGET_POLICY_MEMBER // Internal representation details. friend class cmTargetInternals; diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index ba0ad5986..46c9666ef 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -60,7 +60,7 @@ std::string cmTargetCompileDefinitionsCommand //---------------------------------------------------------------------------- void cmTargetCompileDefinitionsCommand ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, - bool) + bool, bool) { tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str()); } diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h index ec9b071db..585485d2a 100644 --- a/Source/cmTargetCompileDefinitionsCommand.h +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -81,7 +81,7 @@ private: virtual void HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, - bool prepend); + bool prepend, bool system); virtual std::string Join(const std::vector<std::string> &content); }; diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx new file mode 100644 index 000000000..254acc73d --- /dev/null +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -0,0 +1,62 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmTargetCompileOptionsCommand.h" + +bool cmTargetCompileOptionsCommand +::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) +{ + return this->HandleArguments(args, "COMPILE_OPTIONS", PROCESS_BEFORE); +} + +void cmTargetCompileOptionsCommand +::HandleImportedTarget(const std::string &tgt) +{ + cmOStringStream e; + e << "Cannot specify compile options for imported target \"" + << tgt << "\"."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +void cmTargetCompileOptionsCommand +::HandleMissingTarget(const std::string &name) +{ + cmOStringStream e; + e << "Cannot specify compile options for target \"" << name << "\" " + "which is not built by this project."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- +std::string cmTargetCompileOptionsCommand +::Join(const std::vector<std::string> &content) +{ + std::string defs; + std::string sep; + for(std::vector<std::string>::const_iterator it = content.begin(); + it != content.end(); ++it) + { + defs += sep + *it; + sep = ";"; + } + return defs; +} + +//---------------------------------------------------------------------------- +void cmTargetCompileOptionsCommand +::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, + bool, bool) +{ + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmValueWithOrigin entry(this->Join(content), lfbt); + tgt->InsertCompileOption(entry); +} diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h new file mode 100644 index 000000000..b9afd7169 --- /dev/null +++ b/Source/cmTargetCompileOptionsCommand.h @@ -0,0 +1,90 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmTargetCompileOptionsCommand_h +#define cmTargetCompileOptionsCommand_h + +#include "cmTargetPropCommandBase.h" + +class cmTargetCompileOptionsCommand : public cmTargetPropCommandBase +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmTargetCompileOptionsCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector<std::string> const& args, + cmExecutionStatus &status); + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() const { return "target_compile_options";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() const + { + return + "Add compile options to a target."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() const + { + return + " target_compile_options(<target> [BEFORE] " + "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n" + " [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n" + "Specify compile options to use when compiling a given target. " + "The named <target> must have been created by a command such as " + "add_executable or add_library and must not be an IMPORTED target. " + "If BEFORE is specified, the content will be prepended to the property " + "instead of being appended.\n" + "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify " + "the scope of the following arguments. PRIVATE and PUBLIC items will " + "populate the COMPILE_OPTIONS property of <target>. PUBLIC and " + "INTERFACE items will populate the INTERFACE_COMPILE_OPTIONS " + "property of <target>. " + "The following arguments specify compile opitions. " + "Repeated calls for the same <target> append items in the order called." + "\n" + "Arguments to target_compile_options may use \"generator " + "expressions\" with the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS + ; + } + + cmTypeMacro(cmTargetCompileOptionsCommand, cmTargetPropCommandBase); + +private: + virtual void HandleImportedTarget(const std::string &tgt); + virtual void HandleMissingTarget(const std::string &name); + + virtual void HandleDirectContent(cmTarget *tgt, + const std::vector<std::string> &content, + bool prepend, bool system); + virtual std::string Join(const std::vector<std::string> &content); +}; + +#endif diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h index c9d87fb7e..76658887d 100644 --- a/Source/cmTargetExport.h +++ b/Source/cmTargetExport.h @@ -12,6 +12,8 @@ #ifndef cmTargetExport_h #define cmTargetExport_h +#include "cmStandardIncludes.h" + class cmTarget; class cmInstallTargetGenerator; class cmInstallFilesGenerator; @@ -33,6 +35,7 @@ public: cmInstallTargetGenerator* FrameworkGenerator; cmInstallTargetGenerator* BundleGenerator; cmInstallFilesGenerator* HeaderGenerator; + std::string InterfaceIncludeDirectories; ///@} }; diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index 12d0a515f..e7b906c9e 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -15,7 +15,8 @@ bool cmTargetIncludeDirectoriesCommand ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) { - return this->HandleArguments(args, "INCLUDE_DIRECTORIES", PROCESS_BEFORE); + return this->HandleArguments(args, "INCLUDE_DIRECTORIES", + ArgumentFlags(PROCESS_BEFORE | PROCESS_SYSTEM)); } //---------------------------------------------------------------------------- @@ -65,10 +66,39 @@ std::string cmTargetIncludeDirectoriesCommand //---------------------------------------------------------------------------- void cmTargetIncludeDirectoriesCommand ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, - bool prepend) + bool prepend, bool system) { cmListFileBacktrace lfbt; this->Makefile->GetBacktrace(lfbt); cmValueWithOrigin entry(this->Join(content), lfbt); tgt->InsertInclude(entry, prepend); + if (system) + { + tgt->AddSystemIncludeDirectories(content); + } +} + +//---------------------------------------------------------------------------- +void cmTargetIncludeDirectoriesCommand +::HandleInterfaceContent(cmTarget *tgt, + const std::vector<std::string> &content, + bool prepend, bool system) +{ + cmTargetPropCommandBase::HandleInterfaceContent(tgt, content, + prepend, system); + + if (system) + { + std::string joined; + std::string sep; + for(std::vector<std::string>::const_iterator it = content.begin(); + it != content.end(); ++it) + { + joined += sep; + sep = ";"; + joined += *it; + } + tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", + joined.c_str()); + } } diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h index e4bc9cf67..fcc37f06a 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.h +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -54,7 +54,7 @@ public: virtual const char* GetFullDocumentation() const { return - " target_include_directories(<target> [BEFORE] " + " target_include_directories(<target> [SYSTEM] [BEFORE] " "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n" " [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n" "Specify include directories or targets to use when compiling a given " @@ -71,6 +71,14 @@ public: "The following arguments specify include directories. Specified " "include directories may be absolute paths or relative paths. " "Repeated calls for the same <target> append items in the order called." + "If SYSTEM is specified, the compiler will be told the " + "directories are meant as system include directories on some " + "platforms (signalling this setting might achieve effects such as " + "the compiler skipping warnings, or these fixed-install system files " + "not being considered in dependency calculations - see compiler " + "docs). If SYSTEM is used together with PUBLIC or INTERFACE, the " + "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES target property will be " + "populated with the specified directories." "\n" "Arguments to target_include_directories may use \"generator " "expressions\" with the syntax \"$<...>\". " @@ -86,7 +94,11 @@ private: virtual void HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, - bool prepend); + bool prepend, bool system); + virtual void HandleInterfaceContent(cmTarget *tgt, + const std::vector<std::string> &content, + bool prepend, bool system); + virtual std::string Join(const std::vector<std::string> &content); }; diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index b7b7691c8..c2f46a1b1 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -31,6 +31,11 @@ bool cmTargetLinkLibrariesCommand return false; } + if (this->Makefile->IsAlias(args[0].c_str())) + { + this->SetError("can not be used on an ALIAS target."); + return false; + } // Lookup the target for which libraries are specified. this->Target = this->Makefile->GetCMakeInstance() @@ -116,7 +121,7 @@ bool cmTargetLinkLibrariesCommand { if(args[i] == "LINK_INTERFACE_LIBRARIES") { - this->CurrentProcessingState = ProcessingLinkInterface; + this->CurrentProcessingState = ProcessingPlainLinkInterface; if(i != 1) { this->Makefile->IssueMessage( @@ -127,9 +132,26 @@ bool cmTargetLinkLibrariesCommand return true; } } + else if(args[i] == "INTERFACE") + { + if(i != 1 + && this->CurrentProcessingState != ProcessingKeywordPrivateInterface + && this->CurrentProcessingState != ProcessingKeywordPublicInterface + && this->CurrentProcessingState != ProcessingKeywordLinkInterface) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "The INTERFACE option must appear as the second " + "argument, just after the target name." + ); + return true; + } + this->CurrentProcessingState = ProcessingKeywordLinkInterface; + } else if(args[i] == "LINK_PUBLIC") { - if(i != 1 && this->CurrentProcessingState != ProcessingPrivateInterface) + if(i != 1 + && this->CurrentProcessingState != ProcessingPlainPrivateInterface) { this->Makefile->IssueMessage( cmake::FATAL_ERROR, @@ -138,11 +160,28 @@ bool cmTargetLinkLibrariesCommand ); return true; } - this->CurrentProcessingState = ProcessingPublicInterface; + this->CurrentProcessingState = ProcessingPlainPublicInterface; + } + else if(args[i] == "PUBLIC") + { + if(i != 1 + && this->CurrentProcessingState != ProcessingKeywordPrivateInterface + && this->CurrentProcessingState != ProcessingKeywordPublicInterface + && this->CurrentProcessingState != ProcessingKeywordLinkInterface) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "The PUBLIC or PRIVATE option must appear as the second " + "argument, just after the target name." + ); + return true; + } + this->CurrentProcessingState = ProcessingKeywordPublicInterface; } else if(args[i] == "LINK_PRIVATE") { - if(i != 1 && this->CurrentProcessingState != ProcessingPublicInterface) + if(i != 1 + && this->CurrentProcessingState != ProcessingPlainPublicInterface) { this->Makefile->IssueMessage( cmake::FATAL_ERROR, @@ -151,7 +190,23 @@ bool cmTargetLinkLibrariesCommand ); return true; } - this->CurrentProcessingState = ProcessingPrivateInterface; + this->CurrentProcessingState = ProcessingPlainPrivateInterface; + } + else if(args[i] == "PRIVATE") + { + if(i != 1 + && this->CurrentProcessingState != ProcessingKeywordPrivateInterface + && this->CurrentProcessingState != ProcessingKeywordPublicInterface + && this->CurrentProcessingState != ProcessingKeywordLinkInterface) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "The PUBLIC or PRIVATE option must appear as the second " + "argument, just after the target name." + ); + return true; + } + this->CurrentProcessingState = ProcessingKeywordPrivateInterface; } else if(args[i] == "debug") { @@ -184,7 +239,10 @@ bool cmTargetLinkLibrariesCommand { // The link type was specified by the previous argument. haveLLT = false; - this->HandleLibrary(args[i].c_str(), llt); + if (!this->HandleLibrary(args[i].c_str(), llt)) + { + return false; + } } else { @@ -210,7 +268,10 @@ bool cmTargetLinkLibrariesCommand llt = cmTarget::OPTIMIZED; } } - this->HandleLibrary(args[i].c_str(), llt); + if (!this->HandleLibrary(args[i].c_str(), llt)) + { + return false; + } } } @@ -224,12 +285,17 @@ bool cmTargetLinkLibrariesCommand cmSystemTools::SetFatalErrorOccured(); } + const cmPolicies::PolicyStatus policy22Status + = this->Target->GetPolicyStatusCMP0022(); + // If any of the LINK_ options were given, make sure the // LINK_INTERFACE_LIBRARIES target property exists. // Use of any of the new keywords implies awareness of // this property. And if no libraries are named, it should // result in an empty link interface. - if(this->CurrentProcessingState != ProcessingLinkLibraries && + if((policy22Status == cmPolicies::OLD || + policy22Status == cmPolicies::WARN) && + this->CurrentProcessingState != ProcessingLinkLibraries && !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES")) { this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", ""); @@ -252,22 +318,106 @@ cmTargetLinkLibrariesCommand } //---------------------------------------------------------------------------- -void +bool cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt) { + cmTarget::TLLSignature sig = + (this->CurrentProcessingState == ProcessingPlainPrivateInterface + || this->CurrentProcessingState == ProcessingPlainPublicInterface + || this->CurrentProcessingState == ProcessingKeywordPrivateInterface + || this->CurrentProcessingState == ProcessingKeywordPublicInterface + || this->CurrentProcessingState == ProcessingKeywordLinkInterface) + ? cmTarget::KeywordTLLSignature : cmTarget::PlainTLLSignature; + if (!this->Target->PushTLLCommandTrace(sig)) + { + const char *modal = 0; + cmake::MessageType messageType = cmake::AUTHOR_WARNING; + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0023)) + { + case cmPolicies::WARN: + modal = "should"; + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + modal = "must"; + messageType = cmake::FATAL_ERROR; + } + + if(modal) + { + cmOStringStream e; + // If the sig is a keyword form and there is a conflict, the existing + // form must be the plain form. + const char *existingSig + = (sig == cmTarget::KeywordTLLSignature ? "plain" + : "keyword"); + e << this->Makefile->GetPolicies() + ->GetPolicyWarning(cmPolicies::CMP0023) << "\n" + "The " << existingSig << " signature for target_link_libraries " + "has already been used with the target \"" + << this->Target->GetName() << "\". All uses of " + "target_link_libraries with a target " << modal << " be either " + "all-keyword or all-plain.\n"; + this->Target->GetTllSignatureTraces(e, + sig == cmTarget::KeywordTLLSignature + ? cmTarget::PlainTLLSignature + : cmTarget::KeywordTLLSignature); + this->Makefile->IssueMessage(messageType, e.str().c_str()); + if(messageType == cmake::FATAL_ERROR) + { + return false; + } + } + } + // Handle normal case first. - if(this->CurrentProcessingState != ProcessingLinkInterface) + if(this->CurrentProcessingState != ProcessingKeywordLinkInterface + && this->CurrentProcessingState != ProcessingPlainLinkInterface) { this->Makefile ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt); - if (this->CurrentProcessingState != ProcessingPublicInterface) + if(this->CurrentProcessingState == ProcessingLinkLibraries) + { + this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES", + this->Target->GetDebugGeneratorExpressions(lib, llt).c_str()); + return true; + } + else if(this->CurrentProcessingState != ProcessingKeywordPublicInterface + && this->CurrentProcessingState != ProcessingPlainPublicInterface) { - // Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface. - return; + if (this->Target->GetType() == cmTarget::STATIC_LIBRARY) + { + std::string configLib = this->Target + ->GetDebugGeneratorExpressions(lib, llt); + if (cmGeneratorExpression::IsValidTargetName(lib) + || cmGeneratorExpression::Find(lib) != std::string::npos) + { + configLib = "$<LINK_ONLY:" + configLib + ">"; + } + this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES", + configLib.c_str()); + } + // Not a 'public' or 'interface' library. Do not add to interface + // property. + return true; } } + this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES", + this->Target->GetDebugGeneratorExpressions(lib, llt).c_str()); + + const cmPolicies::PolicyStatus policy22Status + = this->Target->GetPolicyStatusCMP0022(); + + if (policy22Status != cmPolicies::OLD + && policy22Status != cmPolicies::WARN) + { + return true; + } + // Get the list of configurations considered to be DEBUG. std::vector<std::string> const& debugConfigs = this->Makefile->GetCMakeInstance()->GetDebugConfigs(); @@ -303,4 +453,5 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, } } } + return true; } diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index c683016dd..2cf6b03ef 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -88,14 +88,19 @@ public: "See the IMPORTED mode of the add_library command for more " "information. " "\n" - "Library dependencies are transitive by default. " + "Library dependencies are transitive by default with this signature. " "When this target is linked into another target then the libraries " "linked to this target will appear on the link line for the other " "target too. " - "See the LINK_INTERFACE_LIBRARIES target property to override the " - "set of transitive link dependencies for a target. " + "This transitive \"link interface\" is stored in the " + "INTERFACE_LINK_LIBRARIES target property when policy CMP0022 is set " + "to NEW and may be overridden by setting the property directly. " + "(" + "When CMP0022 is not set to NEW, transitive linking is builtin " + "but may be overridden by the LINK_INTERFACE_LIBRARIES property. " "Calls to other signatures of this command may set the property " "making any libraries linked exclusively by this signature private." + ")" "\n" "CMake will also propagate \"usage requirements\" from linked library " "targets. " @@ -109,17 +114,38 @@ public: " INTERFACE_POSITION_INDEPENDENT_CODE: Sets POSITION_INDEPENDENT_CODE\n" " or checked for consistency with existing value\n" "\n" + "If an <item> is a library in a Mac OX framework, the Headers " + "directory of the framework will also be processed as a \"usage " + "requirement\". This has the same effect as passing the framework " + "directory as an include directory." + " target_link_libraries(<target>\n" + " <PRIVATE|PUBLIC|INTERFACE> <lib> ...\n" + " [<PRIVATE|PUBLIC|INTERFACE> <lib> ... ] ...])\n" + "The PUBLIC, PRIVATE and INTERFACE keywords can be used to specify " + "both the link dependencies and the link interface in one command. " + "Libraries and targets following PUBLIC are linked to, and are " + "made part of the link interface. Libraries and targets " + "following PRIVATE are linked to, but are not made part of the " + "link interface. Libraries following INTERFACE are appended " + "to the link interface and are not used for linking <target>." + "\n" " target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n" " [[debug|optimized|general] <lib>] ...)\n" "The LINK_INTERFACE_LIBRARIES mode appends the libraries " - "to the LINK_INTERFACE_LIBRARIES and its per-configuration equivalent " - "target properties instead of using them for linking. " - "Libraries specified as \"debug\" are appended to the " + "to the INTERFACE_LINK_LIBRARIES target property instead of using them " + "for linking. If policy CMP0022 is not NEW, then this mode also " + "appends libraries to the LINK_INTERFACE_LIBRARIES and its " + "per-configuration equivalent. This signature " + "is for compatibility only. Prefer the INTERFACE mode instead. " + "Libraries specified as \"debug\" are wrapped in a generator " + "expression to correspond to debug builds. If policy CMP0022 is not " + "NEW, the libraries are also appended to the " "LINK_INTERFACE_LIBRARIES_DEBUG property (or to the properties " "corresponding to configurations listed in the DEBUG_CONFIGURATIONS " "global property if it is set). " "Libraries specified as \"optimized\" are appended to the " - "LINK_INTERFACE_LIBRARIES property. " + "INTERFACE_LINK_LIBRARIES property. If policy CMP0022 is not NEW, " + "they are also appended to the LINK_INTERFACE_LIBRARIES property. " "Libraries specified as \"general\" (or without any keyword) are " "treated as if specified for both \"debug\" and \"optimized\"." "\n" @@ -129,11 +155,15 @@ public: " [<LINK_PRIVATE|LINK_PUBLIC>\n" " [[debug|optimized|general] <lib>] ...])\n" "The LINK_PUBLIC and LINK_PRIVATE modes can be used to specify both " - "the link dependencies and the link interface in one command. " + "the link dependencies and the link interface in one command. This " + "signature is for compatibility only. Prefer the PUBLIC or PRIVATE " + "keywords instead. " "Libraries and targets following LINK_PUBLIC are linked to, and are " - "made part of the LINK_INTERFACE_LIBRARIES. Libraries and targets " - "following LINK_PRIVATE are linked to, but are not made part of the " - "LINK_INTERFACE_LIBRARIES. " + "made part of the INTERFACE_LINK_LIBRARIES. If policy CMP0022 is not " + "NEW, they are also made part of the LINK_INTERFACE_LIBRARIES. " + "Libraries and targets following LINK_PRIVATE are linked to, but are " + "not made part of the INTERFACE_LINK_LIBRARIES (or " + "LINK_INTERFACE_LIBRARIES)." "\n" "The library dependency graph is normally acyclic (a DAG), but in the " "case of mutually-dependent STATIC libraries CMake allows the graph " @@ -173,14 +203,17 @@ private: cmTarget* Target; enum ProcessingState { ProcessingLinkLibraries, - ProcessingLinkInterface, - ProcessingPublicInterface, - ProcessingPrivateInterface + ProcessingPlainLinkInterface, + ProcessingKeywordLinkInterface, + ProcessingPlainPublicInterface, + ProcessingKeywordPublicInterface, + ProcessingPlainPrivateInterface, + ProcessingKeywordPrivateInterface }; ProcessingState CurrentProcessingState; - void HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt); + bool HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt); }; diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 771097ca2..1862cb696 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -19,13 +19,18 @@ bool cmTargetPropCommandBase ::HandleArguments(std::vector<std::string> const& args, const char *prop, ArgumentFlags flags) { - if(args.size() < 3) + if(args.size() < 2) { this->SetError("called with incorrect number of arguments"); return false; } // Lookup the target for which libraries are specified. + if (this->Makefile->IsAlias(args[0].c_str())) + { + this->SetError("can not be used on an ALIAS target."); + return false; + } this->Target = this->Makefile->GetCMakeInstance() ->GetGlobalGenerator()->FindTarget(0, args[0].c_str()); @@ -48,12 +53,24 @@ bool cmTargetPropCommandBase return false; } + bool system = false; unsigned int argIndex = 1; + if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM") + { + if (args.size() < 3) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + system = true; + ++argIndex; + } + bool prepend = false; if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE") { - if (args.size() < 4) + if (args.size() < 3) { this->SetError("called with incorrect number of arguments"); return false; @@ -66,7 +83,7 @@ bool cmTargetPropCommandBase while (argIndex < args.size()) { - if (!this->ProcessContentArgs(args, argIndex, prepend)) + if (!this->ProcessContentArgs(args, argIndex, prepend, system)) { return false; } @@ -77,7 +94,7 @@ bool cmTargetPropCommandBase //---------------------------------------------------------------------------- bool cmTargetPropCommandBase ::ProcessContentArgs(std::vector<std::string> const& args, - unsigned int &argIndex, bool prepend) + unsigned int &argIndex, bool prepend, bool system) { const std::string scope = args[argIndex]; @@ -105,12 +122,12 @@ bool cmTargetPropCommandBase || args[i] == "PRIVATE" || args[i] == "INTERFACE" ) { - this->PopulateTargetProperies(scope, content, prepend); + this->PopulateTargetProperies(scope, content, prepend, system); return true; } content.push_back(args[i]); } - this->PopulateTargetProperies(scope, content, prepend); + this->PopulateTargetProperies(scope, content, prepend, system); return true; } @@ -118,27 +135,35 @@ bool cmTargetPropCommandBase void cmTargetPropCommandBase ::PopulateTargetProperies(const std::string &scope, const std::vector<std::string> &content, - bool prepend) + bool prepend, bool system) { if (scope == "PRIVATE" || scope == "PUBLIC") { - this->HandleDirectContent(this->Target, content, prepend); + this->HandleDirectContent(this->Target, content, prepend, system); } if (scope == "INTERFACE" || scope == "PUBLIC") { - if (prepend) - { - const std::string propName = std::string("INTERFACE_") + this->Property; - const char *propValue = this->Target->GetProperty(propName.c_str()); - const std::string totalContent = this->Join(content) + (propValue - ? std::string(";") + propValue - : std::string()); - this->Target->SetProperty(propName.c_str(), totalContent.c_str()); - } - else - { - this->Target->AppendProperty(("INTERFACE_" + this->Property).c_str(), - this->Join(content).c_str()); - } + this->HandleInterfaceContent(this->Target, content, prepend, system); + } +} + +//---------------------------------------------------------------------------- +void cmTargetPropCommandBase::HandleInterfaceContent(cmTarget *tgt, + const std::vector<std::string> &content, + bool prepend, bool) +{ + if (prepend) + { + const std::string propName = std::string("INTERFACE_") + this->Property; + const char *propValue = tgt->GetProperty(propName.c_str()); + const std::string totalContent = this->Join(content) + (propValue + ? std::string(";") + propValue + : std::string()); + tgt->SetProperty(propName.c_str(), totalContent.c_str()); + } + else + { + tgt->AppendProperty(("INTERFACE_" + this->Property).c_str(), + this->Join(content).c_str()); } } diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index 8047a48aa..690582fdd 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -25,7 +25,8 @@ public: enum ArgumentFlags { NO_FLAGS = 0, - PROCESS_BEFORE = 1 + PROCESS_BEFORE = 1, + PROCESS_SYSTEM = 2 }; bool HandleArguments(std::vector<std::string> const& args, @@ -36,20 +37,24 @@ protected: std::string Property; cmTarget *Target; + virtual void HandleInterfaceContent(cmTarget *tgt, + const std::vector<std::string> &content, + bool prepend, bool system); private: virtual void HandleImportedTarget(const std::string &tgt) = 0; virtual void HandleMissingTarget(const std::string &name) = 0; virtual void HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, - bool prepend) = 0; + bool prepend, bool system) = 0; + virtual std::string Join(const std::vector<std::string> &content) = 0; bool ProcessContentArgs(std::vector<std::string> const& args, - unsigned int &argIndex, bool prepend); + unsigned int &argIndex, bool prepend, bool system); void PopulateTargetProperies(const std::string &scope, const std::vector<std::string> &content, - bool prepend); + bool prepend, bool system); }; #endif diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index 912ec7634..0904431d1 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -135,7 +135,7 @@ void cmTest::DefineProperties(cmake *cm) "If the output matches this regular expression the test will fail.", "If set, if the output matches one of " "specified regular expressions, the test will fail." - "For example: PASS_REGULAR_EXPRESSION \"[^a-z]Error;ERROR;Failed\""); + "For example: FAIL_REGULAR_EXPRESSION \"[^a-z]Error;ERROR;Failed\""); cm->DefineProperty ("LABELS", cmProperty::TEST, diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h index 6caa130ce..a20594cbe 100644 --- a/Source/cmTryCompileCommand.h +++ b/Source/cmTryCompileCommand.h @@ -64,19 +64,19 @@ public: "Specify targetName to build a specific target instead of the 'all' or " "'ALL_BUILD' target." "\n" - " try_compile(RESULT_VAR <bindir> <srcfile>\n" + " try_compile(RESULT_VAR <bindir> <srcfile|SOURCES srcfile...>\n" " [CMAKE_FLAGS flags...]\n" " [COMPILE_DEFINITIONS flags...]\n" " [LINK_LIBRARIES libs...]\n" " [OUTPUT_VARIABLE <var>]\n" - " [COPY_FILE <fileName>])\n" - "Try building a source file into an executable. " - "In this form the user need only supply a source file that defines " - "a 'main'. " - "CMake will create a CMakeLists.txt file to build the source " + " [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]])\n" + "Try building an executable from one or more source files. " + "In this form the user need only supply one or more source files " + "that include a definition for 'main'. " + "CMake will create a CMakeLists.txt file to build the source(s) " "as an executable. " "Specify COPY_FILE to get a copy of the linked executable at the " - "given fileName." + "given fileName and optionally COPY_FILE_ERROR to capture any error." "\n" "In this version all files in bindir/CMakeFiles/CMakeTmp " "will be cleaned automatically. For debugging, --debug-trycompile can " diff --git a/Source/cmVS10LinkFlagTable.h b/Source/cmVS10LinkFlagTable.h index 64febbb52..5d1562002 100644 --- a/Source/cmVS10LinkFlagTable.h +++ b/Source/cmVS10LinkFlagTable.h @@ -201,7 +201,7 @@ static cmVS7FlagTable cmVS10LinkFlagTable[] = cmVS7FlagTable::UserValueRequired}, {"GenerateMapFile", "MAP", "", "true", cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, - {"MapFileName", "MAP", "Generate Map File", "", + {"MapFileName", "MAP:", "Generate Map File", "", cmVS7FlagTable::UserValueRequired}, //String List Properties diff --git a/Source/cmVS11LinkFlagTable.h b/Source/cmVS11LinkFlagTable.h index ea0d0f0b0..b4587a836 100644 --- a/Source/cmVS11LinkFlagTable.h +++ b/Source/cmVS11LinkFlagTable.h @@ -227,7 +227,7 @@ static cmVS7FlagTable cmVS11LinkFlagTable[] = cmVS7FlagTable::UserValueRequired}, {"GenerateMapFile", "MAP", "", "true", cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, - {"MapFileName", "MAP", "Generate Map File", "", + {"MapFileName", "MAP:", "Generate Map File", "", cmVS7FlagTable::UserValueRequired}, //String List Properties diff --git a/Source/cmVS12LinkFlagTable.h b/Source/cmVS12LinkFlagTable.h index ce32e3815..73d450a9d 100644 --- a/Source/cmVS12LinkFlagTable.h +++ b/Source/cmVS12LinkFlagTable.h @@ -227,7 +227,7 @@ static cmVS7FlagTable cmVS12LinkFlagTable[] = cmVS7FlagTable::UserValueRequired}, {"GenerateMapFile", "MAP", "", "true", cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, - {"MapFileName", "MAP", "Generate Map File", "", + {"MapFileName", "MAP:", "Generate Map File", "", cmVS7FlagTable::UserValueRequired}, //String List Properties diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx index f5fdca465..8ad6fce8f 100644 --- a/Source/cmVariableWatch.cxx +++ b/Source/cmVariableWatch.cxx @@ -15,6 +15,7 @@ static const char* const cmVariableWatchAccessStrings[] = { "READ_ACCESS", "UNKNOWN_READ_ACCESS", + "UNKNOWN_DEFINED_ACCESS", "ALLOWED_UNKNOWN_READ_ACCESS", "MODIFIED_ACCESS", "REMOVED_ACCESS", @@ -36,37 +37,63 @@ cmVariableWatch::cmVariableWatch() cmVariableWatch::~cmVariableWatch() { + cmVariableWatch::StringToVectorOfPairs::iterator svp_it; + + for ( svp_it = this->WatchMap.begin(); + svp_it != this->WatchMap.end(); ++svp_it ) + { + cmVariableWatch::VectorOfPairs::iterator p_it; + + for ( p_it = svp_it->second.begin(); + p_it != svp_it->second.end(); ++p_it ) + { + delete *p_it; + } + } } -void cmVariableWatch::AddWatch(const std::string& variable, - WatchMethod method, void* client_data /*=0*/) +bool cmVariableWatch::AddWatch(const std::string& variable, + WatchMethod method, void* client_data /*=0*/, + DeleteData delete_data /*=0*/) { - cmVariableWatch::Pair p; - p.Method = method; - p.ClientData = client_data; + cmVariableWatch::Pair* p = new cmVariableWatch::Pair; + p->Method = method; + p->ClientData = client_data; + p->DeleteDataCall = delete_data; cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable]; cmVariableWatch::VectorOfPairs::size_type cc; for ( cc = 0; cc < vp->size(); cc ++ ) { - cmVariableWatch::Pair* pair = &(*vp)[cc]; - if ( pair->Method == method ) + cmVariableWatch::Pair* pair = (*vp)[cc]; + if ( pair->Method == method && + client_data && client_data == pair->ClientData) { - (*vp)[cc] = p; - return; + // Callback already exists + return false; } } vp->push_back(p); + return true; } void cmVariableWatch::RemoveWatch(const std::string& variable, - WatchMethod method) + WatchMethod method, + void* client_data /*=0*/) { + if ( !this->WatchMap.count(variable) ) + { + return; + } cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable]; cmVariableWatch::VectorOfPairs::iterator it; for ( it = vp->begin(); it != vp->end(); ++it ) { - if ( it->Method == method ) + if ( (*it)->Method == method && + // If client_data is NULL, we want to disconnect all watches against + // the given method; otherwise match ClientData as well. + (!client_data || (client_data == (*it)->ClientData))) { + delete *it; vp->erase(it); return; } @@ -86,7 +113,7 @@ void cmVariableWatch::VariableAccessed(const std::string& variable, cmVariableWatch::VectorOfPairs::const_iterator it; for ( it = vp->begin(); it != vp->end(); it ++ ) { - it->Method(variable, access_type, it->ClientData, + (*it)->Method(variable, access_type, (*it)->ClientData, newValue, mf); } } diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h index 7dd4ac5e6..790c75acc 100644 --- a/Source/cmVariableWatch.h +++ b/Source/cmVariableWatch.h @@ -26,6 +26,7 @@ class cmVariableWatch public: typedef void (*WatchMethod)(const std::string& variable, int access_type, void* client_data, const char* newValue, const cmMakefile* mf); + typedef void (*DeleteData)(void* client_data); cmVariableWatch(); ~cmVariableWatch(); @@ -33,9 +34,10 @@ public: /** * Add watch to the variable */ - void AddWatch(const std::string& variable, WatchMethod method, - void* client_data=0); - void RemoveWatch(const std::string& variable, WatchMethod method); + bool AddWatch(const std::string& variable, WatchMethod method, + void* client_data=0, DeleteData delete_data=0); + void RemoveWatch(const std::string& variable, WatchMethod method, + void* client_data=0); /** * This method is called when variable is accessed @@ -67,10 +69,18 @@ protected: { WatchMethod Method; void* ClientData; - Pair() : Method(0), ClientData(0) {} + DeleteData DeleteDataCall; + Pair() : Method(0), ClientData(0), DeleteDataCall(0) {} + ~Pair() + { + if (this->DeleteDataCall && this->ClientData) + { + this->DeleteDataCall(this->ClientData); + } + } }; - typedef std::vector< Pair > VectorOfPairs; + typedef std::vector< Pair* > VectorOfPairs; typedef std::map<cmStdString, VectorOfPairs > StringToVectorOfPairs; StringToVectorOfPairs WatchMap; diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index a432943ae..33e159bce 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -14,63 +14,27 @@ #include "cmVariableWatch.h" //---------------------------------------------------------------------------- -static void cmVariableWatchCommandVariableAccessed( - const std::string& variable, int access_type, void* client_data, - const char* newValue, const cmMakefile* mf) +struct cmVariableWatchCallbackData { - cmVariableWatchCommand* command - = static_cast<cmVariableWatchCommand*>(client_data); - command->VariableAccessed(variable, access_type, newValue, mf); -} + bool InCallback; + std::string Command; +}; //---------------------------------------------------------------------------- -cmVariableWatchCommand::cmVariableWatchCommand() -{ - this->InCallback = false; -} - -//---------------------------------------------------------------------------- -bool cmVariableWatchCommand -::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) +static void cmVariableWatchCommandVariableAccessed( + const std::string& variable, int access_type, void* client_data, + const char* newValue, const cmMakefile* mf) { - if ( args.size() < 1 ) - { - this->SetError("must be called with at least one argument."); - return false; - } - std::string variable = args[0]; - if ( args.size() > 1 ) - { - std::string command = args[1]; - this->Handlers[variable].Commands.push_back(args[1]); - } - if ( variable == "CMAKE_CURRENT_LIST_FILE" ) - { - cmOStringStream ostr; - ostr << "cannot be set on the variable: " << variable.c_str(); - this->SetError(ostr.str().c_str()); - return false; - } + cmVariableWatchCallbackData* data + = static_cast<cmVariableWatchCallbackData*>(client_data); - this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch( - variable, cmVariableWatchCommandVariableAccessed, this); - - return true; -} - -//---------------------------------------------------------------------------- -void cmVariableWatchCommand::VariableAccessed(const std::string& variable, - int access_type, const char* newValue, const cmMakefile* mf) -{ - if ( this->InCallback ) + if ( data->InCallback ) { return; } - this->InCallback = true; + data->InCallback = true; cmListFileFunction newLFF; - cmVariableWatchCommandHandler *handler = &this->Handlers[variable]; - cmVariableWatchCommandHandler::VectorOfCommands::iterator it; cmListFileArgument arg; bool processed = false; const char* accessString = cmVariableWatch::GetAccessAsString(access_type); @@ -80,22 +44,25 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable, cmMakefile* makefile = const_cast<cmMakefile*>(mf); std::string stack = makefile->GetProperty("LISTFILE_STACK"); - for ( it = handler->Commands.begin(); it != handler->Commands.end(); - ++ it ) + if ( !data->Command.empty() ) { - std::string command = *it; newLFF.Arguments.clear(); newLFF.Arguments.push_back( - cmListFileArgument(variable, true, "unknown", 9999)); + cmListFileArgument(variable, cmListFileArgument::Quoted, + "unknown", 9999)); newLFF.Arguments.push_back( - cmListFileArgument(accessString, true, "unknown", 9999)); + cmListFileArgument(accessString, cmListFileArgument::Quoted, + "unknown", 9999)); newLFF.Arguments.push_back( - cmListFileArgument(newValue?newValue:"", true, "unknown", 9999)); + cmListFileArgument(newValue?newValue:"", cmListFileArgument::Quoted, + "unknown", 9999)); newLFF.Arguments.push_back( - cmListFileArgument(currentListFile, true, "unknown", 9999)); + cmListFileArgument(currentListFile, cmListFileArgument::Quoted, + "unknown", 9999)); newLFF.Arguments.push_back( - cmListFileArgument(stack, true, "unknown", 9999)); - newLFF.Name = command; + cmListFileArgument(stack, cmListFileArgument::Quoted, + "unknown", 9999)); + newLFF.Name = data->Command; newLFF.FilePath = "Some weird path"; newLFF.Line = 9999; cmExecutionStatus status; @@ -106,10 +73,10 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable, cmOStringStream error; error << "Error in cmake code at\n" << arg.FilePath << ":" << arg.Line << ":\n" - << "A command failed during the invocation of callback\"" - << command << "\"."; + << "A command failed during the invocation of callback \"" + << data->Command << "\"."; cmSystemTools::Error(error.str().c_str()); - this->InCallback = false; + data->InCallback = false; return; } processed = true; @@ -117,24 +84,76 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable, if ( !processed ) { cmOStringStream msg; - msg << "* Variable \"" << variable.c_str() << "\" was accessed using " - << accessString << " in: " << currentListFile << std::endl; - msg << " The value of the variable: \"" << newValue << "\"" << std::endl; - msg << " The list file stack: " << stack.c_str(); - cmSystemTools::Message(msg.str().c_str()); - std::vector<std::string> vars = makefile->GetDefinitions(); - cmOStringStream msg2; - size_t cc; - for ( cc = 0; cc < vars.size(); cc ++ ) - { - if ( vars[cc] == variable ) - { - continue; - } - msg2 << vars[cc] << " = \"" - << makefile->GetDefinition(vars[cc].c_str()) << "\"" << std::endl; - } - //cmSystemTools::Message(msg2.str().c_str()); + msg << "Variable \"" << variable.c_str() << "\" was accessed using " + << accessString << " with value \"" << (newValue?newValue:"") << "\"."; + makefile->IssueMessage(cmake::LOG, msg.str()); + } + + data->InCallback = false; +} + +//---------------------------------------------------------------------------- +static void deleteVariableWatchCallbackData(void* client_data) +{ + cmVariableWatchCallbackData* data + = static_cast<cmVariableWatchCallbackData*>(client_data); + delete data; +} + +//---------------------------------------------------------------------------- +cmVariableWatchCommand::cmVariableWatchCommand() +{ +} + +//---------------------------------------------------------------------------- +cmVariableWatchCommand::~cmVariableWatchCommand() +{ + std::set<std::string>::const_iterator it; + for ( it = this->WatchedVariables.begin(); + it != this->WatchedVariables.end(); + ++it ) + { + this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch( + *it, cmVariableWatchCommandVariableAccessed); + } +} + +//---------------------------------------------------------------------------- +bool cmVariableWatchCommand +::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) +{ + if ( args.size() < 1 ) + { + this->SetError("must be called with at least one argument."); + return false; + } + std::string variable = args[0]; + std::string command; + if ( args.size() > 1 ) + { + command = args[1]; } - this->InCallback = false; + if ( variable == "CMAKE_CURRENT_LIST_FILE" ) + { + cmOStringStream ostr; + ostr << "cannot be set on the variable: " << variable.c_str(); + this->SetError(ostr.str().c_str()); + return false; + } + + cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData; + + data->InCallback = false; + data->Command = command; + + this->WatchedVariables.insert(variable); + if ( !this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch( + variable, cmVariableWatchCommandVariableAccessed, + data, deleteVariableWatchCallbackData) ) + { + deleteVariableWatchCallbackData(data); + return false; + } + + return true; } diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h index 3abc08894..545535c40 100644 --- a/Source/cmVariableWatchCommand.h +++ b/Source/cmVariableWatchCommand.h @@ -14,13 +14,6 @@ #include "cmCommand.h" -class cmVariableWatchCommandHandler -{ -public: - typedef std::vector<std::string> VectorOfCommands; - VectorOfCommands Commands; -}; - /** \class cmVariableWatchCommand * \brief Watch when the variable changes and invoke command * @@ -39,6 +32,9 @@ public: //! Default constructor cmVariableWatchCommand(); + //! Destructor. + ~cmVariableWatchCommand(); + /** * This is called when the command is first encountered in * the CMakeLists.txt file. @@ -83,13 +79,8 @@ public: cmTypeMacro(cmVariableWatchCommand, cmCommand); - void VariableAccessed(const std::string& variable, int access_type, - const char* newValue, const cmMakefile* mf); - protected: - std::map<std::string, cmVariableWatchCommandHandler> Handlers; - - bool InCallback; + std::set<std::string> WatchedVariables; }; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 9cfb3703e..6376376a0 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -216,12 +216,16 @@ void cmVisualStudio10TargetGenerator::Generate() // Write the encoding header into the file char magic[] = {0xEF,0xBB, 0xBF}; this->BuildFileStream->write(magic, 3); - this->WriteString("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",0); - this->WriteString("<Project DefaultTargets=\"Build\" " - "ToolsVersion=\"4.0\" " - "xmlns=\"http://schemas.microsoft.com/" - "developer/msbuild/2003\">\n", - 0); + + //get the tools version to use + const std::string toolsVer(this->GlobalGenerator->GetToolsVersion()); + std::string project_defaults="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; + project_defaults.append("<Project DefaultTargets=\"Build\" ToolsVersion=\""); + project_defaults.append(toolsVer +"\" "); + project_defaults.append( + "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"); + this->WriteString(project_defaults.c_str(),0); + this->WriteProjectConfigurations(); this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1); this->WriteString("<ProjectGUID>", 2); @@ -274,6 +278,15 @@ void cmVisualStudio10TargetGenerator::Generate() "</Keyword>\n"; } + const char* vsGlobalRootNamespace = + this->Target->GetProperty("VS_GLOBAL_ROOTNAMESPACE"); + if(vsGlobalRootNamespace) + { + this->WriteString("<RootNamespace>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalRootNamespace) << + "</RootNamespace>\n"; + } + this->WriteString("<Platform>", 2); (*this->BuildFileStream) << this->Platform << "</Platform>\n"; const char* projLabel = this->Target->GetProperty("PROJECT_LABEL"); @@ -283,6 +296,13 @@ void cmVisualStudio10TargetGenerator::Generate() } this->WriteString("<ProjectName>", 2); (*this->BuildFileStream) << projLabel << "</ProjectName>\n"; + if(const char* targetFrameworkVersion = this->Target->GetProperty( + "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) + { + this->WriteString("<TargetFrameworkVersion>", 2); + (*this->BuildFileStream) << targetFrameworkVersion + << "</TargetFrameworkVersion>\n"; + } this->WriteString("</PropertyGroup>\n", 1); this->WriteString("<Import Project=" "\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n", @@ -291,6 +311,11 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteString( "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n", 1); this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1); + if (this->GlobalGenerator->IsMasmEnabled()) + { + this->WriteString("<Import Project=\"$(VCTargetsPath)\\" + "BuildCustomizations\\masm.props\" />\n", 2); + } this->WriteString("</ImportGroup>\n", 1); this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1); this->WriteString("<Import Project=\"" VS10_USER_PROPS "\"" @@ -303,12 +328,18 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteCustomCommands(); this->WriteAllSources(); this->WriteDotNetReferences(); + this->WriteEmbeddedResourceGroup(); this->WriteWinRTReferences(); this->WriteProjectReferences(); this->WriteString( "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\"" " />\n", 1); this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1); + if (this->GlobalGenerator->IsMasmEnabled()) + { + this->WriteString("<Import Project=\"$(VCTargetsPath)\\" + "BuildCustomizations\\masm.targets\" />\n", 2); + } this->WriteString("</ImportGroup>\n", 1); this->WriteString("</Project>", 0); // The groups are stored in a separate file for VS 10 @@ -341,6 +372,47 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences() } } +void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() +{ + std::vector<cmSourceFile*> const& resxObjs = + this->GeneratorTarget->ResxSources; + if(!resxObjs.empty()) + { + this->WriteString("<ItemGroup>\n", 1); + for(std::vector<cmSourceFile*>::const_iterator oi = resxObjs.begin(); + oi != resxObjs.end(); ++oi) + { + std::string obj = (*oi)->GetFullPath(); + this->WriteString("<EmbeddedResource Include=\"", 2); + this->ConvertToWindowsSlash(obj); + (*this->BuildFileStream ) << obj << "\">\n"; + + this->WriteString("<DependentUpon>", 3); + std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h"; + (*this->BuildFileStream ) << hFileName; + this->WriteString("</DependentUpon>\n", 3); + + std::vector<std::string> const * configs = + this->GlobalGenerator->GetConfigurations(); + for(std::vector<std::string>::const_iterator i = configs->begin(); + i != configs->end(); ++i) + { + this->WritePlatformConfigTag("LogicalName", i->c_str(), 3); + if(this->Target->GetProperty("VS_GLOBAL_ROOTNAMESPACE")) + { + (*this->BuildFileStream ) << "$(RootNamespace)."; + } + (*this->BuildFileStream ) << "%(Filename)"; + (*this->BuildFileStream ) << ".resources"; + (*this->BuildFileStream ) << "</LogicalName>\n"; + } + + this->WriteString("</EmbeddedResource>\n", 2); + } + this->WriteString("</ItemGroup>\n", 1); + } +} + void cmVisualStudio10TargetGenerator::WriteWinRTReferences() { std::vector<std::string> references; @@ -467,6 +539,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() this->WriteString("<WindowsAppContainer>true" "</WindowsAppContainer>\n", 2); } + this->WriteString("</PropertyGroup>\n", 1); } } @@ -647,18 +720,40 @@ void cmVisualStudio10TargetGenerator::WriteGroups() fout.write(magic, 3); cmGeneratedFileStream* save = this->BuildFileStream; this->BuildFileStream = & fout; - this->WriteString("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" - "<Project " - "ToolsVersion=\"4.0\" " - "xmlns=\"http://schemas.microsoft.com/" - "developer/msbuild/2003\">\n", - 0); + + //get the tools version to use + const std::string toolsVer(this->GlobalGenerator->GetToolsVersion()); + std::string project_defaults="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; + project_defaults.append("<Project ToolsVersion=\""); + project_defaults.append(toolsVer +"\" "); + project_defaults.append( + "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"); + this->WriteString(project_defaults.c_str(),0); + for(ToolSourceMap::const_iterator ti = this->Tools.begin(); ti != this->Tools.end(); ++ti) { this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups); } + std::vector<cmSourceFile*> const& resxObjs = + this->GeneratorTarget->ResxSources; + if(!resxObjs.empty()) + { + this->WriteString("<ItemGroup>\n", 1); + for(std::vector<cmSourceFile*>::const_iterator oi = resxObjs.begin(); + oi != resxObjs.end(); ++oi) + { + std::string obj = (*oi)->GetFullPath(); + this->WriteString("<EmbeddedResource Include=\"", 2); + this->ConvertToWindowsSlash(obj); + (*this->BuildFileStream ) << obj << "\">\n"; + this->WriteString("<Filter>Resource Files</Filter>\n", 3); + this->WriteString("</EmbeddedResource>\n", 2); + } + this->WriteString("</ItemGroup>\n", 1); + } + // Add object library contents as external objects. std::vector<std::string> objs; this->GeneratorTarget->UseObjectLibraries(objs); @@ -713,6 +808,23 @@ void cmVisualStudio10TargetGenerator::WriteGroups() << "</UniqueIdentifier>\n"; this->WriteString("</Filter>\n", 2); } + + if(!this->GeneratorTarget->ResxSources.empty()) + { + this->WriteString("<Filter Include=\"Resource Files\">\n", 2); + std::string guidName = "SG_Filter_Resource Files"; + this->GlobalGenerator->CreateGUID(guidName.c_str()); + this->WriteString("<UniqueIdentifier>", 3); + std::string guid = + this->GlobalGenerator->GetGUID(guidName.c_str()); + (*this->BuildFileStream) << "{" << guid << "}" + << "</UniqueIdentifier>\n"; + this->WriteString("<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;", 3); + (*this->BuildFileStream) << "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;"; + (*this->BuildFileStream) << "mfcribbon-ms</Extensions>\n"; + this->WriteString("</Filter>\n", 2); + } + this->WriteString("</ItemGroup>\n", 1); this->WriteString("</Project>\n", 0); // restore stream pointer @@ -844,8 +956,20 @@ void cmVisualStudio10TargetGenerator::WriteSource( } this->ConvertToWindowsSlash(sourceFile); this->WriteString("<", 2); - (*this->BuildFileStream ) << tool << - " Include=\"" << sourceFile << "\"" << (end? end : " />\n"); + (*this->BuildFileStream ) << tool << " Include=\"" << sourceFile << "\""; + + if(sf->GetExtension() == "h" && + this->IsResxHeader(sf->GetFullPath())) + { + (*this->BuildFileStream ) << ">\n"; + this->WriteString("<FileType>CppForm</FileType>\n", 3); + this->WriteString("</ClInclude>\n", 2); + } + else + { + (*this->BuildFileStream ) << (end? end : " />\n"); + } + ToolSource toolSource = {sf, forceRelative}; this->Tools[tool].push_back(toolSource); } @@ -876,24 +1000,37 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() si != this->GeneratorTarget->ObjectSources.end(); ++si) { const char* lang = (*si)->GetLanguage(); - bool cl = strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0; - bool rc = strcmp(lang, "RC") == 0; - const char* tool = cl? "ClCompile" : (rc? "ResourceCompile" : "None"); - this->WriteSource(tool, *si, " "); - // ouput any flags specific to this source file - if(cl && this->OutputSourceSpecificFlags(*si)) + const char* tool = NULL; + if (strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0) { - // if the source file has specific flags the tag - // is ended on a new line - this->WriteString("</ClCompile>\n", 2); + tool = "ClCompile"; } - else if(rc && this->OutputSourceSpecificFlags(*si)) + else if (strcmp(lang, "ASM_MASM") == 0 && + this->GlobalGenerator->IsMasmEnabled()) { - this->WriteString("</ResourceCompile>\n", 2); + tool = "MASM"; + } + else if (strcmp(lang, "RC") == 0) + { + tool = "ResourceCompile"; + } + + if (tool) + { + this->WriteSource(tool, *si, " "); + if (this->OutputSourceSpecificFlags(*si)) + { + this->WriteString("</", 2); + (*this->BuildFileStream ) << tool << ">\n"; + } + else + { + (*this->BuildFileStream ) << " />\n"; + } } else { - (*this->BuildFileStream ) << " />\n"; + this->WriteSource("None", *si); } } @@ -1192,7 +1329,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( if(!linkLanguage) { cmSystemTools::Error - ("CMake can not determine linker language for target:", + ("CMake can not determine linker language for target: ", this->Name.c_str()); return false; } @@ -1219,21 +1356,21 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( { flags += " /TP "; } + this->LocalGenerator->AddCompileOptions(flags, this->Target, + linkLanguage, configName.c_str()); } - // Add the target-specific flags. - if(const char* targetFlags = this->Target->GetProperty("COMPILE_FLAGS")) - { - flags += " "; - flags += targetFlags; - } + // Get preprocessor definitions for this directory. std::string defineFlags = this->Target->GetMakefile()->GetDefineFlags(); clOptions.FixExceptionHandlingDefault(); clOptions.AddFlag("PrecompiledHeader", "NotUsing"); + std::string asmLocation = configName + "/"; + clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str()); clOptions.Parse(flags.c_str()); clOptions.Parse(defineFlags.c_str()); - clOptions.AddDefines(this->Target->GetCompileDefinitions( - configName.c_str()).c_str()); + std::vector<std::string> targetDefines; + this->Target->GetCompileDefinitions(targetDefines, configName.c_str()); + clOptions.AddDefines(targetDefines); clOptions.SetVerboseMakefile( this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); @@ -1272,18 +1409,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", "CXX"); - this->WriteString("<AssemblerListingLocation>", 3); - *this->BuildFileStream << configName - << "</AssemblerListingLocation>\n"; this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3); - if(this->Target->GetType() != cmTarget::OBJECT_LIBRARY) - { - this->WriteString("<ProgramDataBaseFileName>", 3); - *this->BuildFileStream << this->Target->GetPDBDirectory(configName.c_str()) - << "/" - << this->Target->GetPDBName(configName.c_str()) - << "</ProgramDataBaseFileName>\n"; - } this->WriteString("</ClCompile>\n", 2); } @@ -1294,7 +1420,9 @@ OutputIncludes(std::vector<std::string> const & includes) for(std::vector<std::string>::const_iterator i = includes.begin(); i != includes.end(); ++i) { - *this->BuildFileStream << *i << ";"; + std::string incDir = *i; + this->ConvertToWindowsSlash(incDir); + *this->BuildFileStream << cmVS10EscapeXML(incDir) << ";"; } this->WriteString("%(AdditionalIncludeDirectories)" "</AdditionalIncludeDirectories>\n", 0); @@ -1322,20 +1450,17 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config) { return; } - const char* libflags = this->Target->GetProperty("STATIC_LIBRARY_FLAGS"); - std::string flagsConfigVar = "STATIC_LIBRARY_FLAGS_"; - flagsConfigVar += cmSystemTools::UpperCase(config); - const char* libflagsConfig = - this->Target->GetProperty(flagsConfigVar.c_str()); - if(libflags || libflagsConfig) + std::string libflags; + this->LocalGenerator->GetStaticLibraryFlags(libflags, + cmSystemTools::UpperCase(config), this->Target); + if(!libflags.empty()) { this->WriteString("<Lib>\n", 2); cmVisualStudioGeneratorOptions libOptions(this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker, cmVSGetLibFlagTable(this->LocalGenerator), 0, this); - libOptions.Parse(libflags?libflags:""); - libOptions.Parse(libflagsConfig?libflagsConfig:""); + libOptions.Parse(libflags.c_str()); libOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); libOptions.OutputFlagMap(*this->BuildFileStream, " "); this->WriteString("</Lib>\n", 2); @@ -1377,7 +1502,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) if(!linkLanguage) { cmSystemTools::Error - ("CMake can not determine linker language for target:", + ("CMake can not determine linker language for target: ", this->Name.c_str()); return false; } @@ -1428,11 +1553,11 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) } if ( this->Target->GetPropertyAsBool("WIN32_EXECUTABLE") ) { - flags += " /SUBSYSTEM:WINDOWS"; + linkOptions.AddFlag("SubSystem", "Windows"); } else { - flags += " /SUBSYSTEM:CONSOLE"; + linkOptions.AddFlag("SubSystem", "Console"); } std::string standardLibsVar = "CMAKE_"; standardLibsVar += linkLanguage; @@ -1459,7 +1584,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) if(!pcli) { cmSystemTools::Error - ("CMake can not compute cmComputeLinkInformation for target:", + ("CMake can not compute cmComputeLinkInformation for target: ", this->Name.c_str()); return false; } @@ -1591,6 +1716,21 @@ void cmVisualStudio10TargetGenerator:: WriteMidlOptions(std::string const& /*config*/, std::vector<std::string> const & includes) { + // This processes *any* of the .idl files specified in the project's file + // list (and passed as the item metadata %(Filename) expressing the rule + // input filename) into output files at the per-config *build* dir + // ($(IntDir)) each. + // + // IOW, this MIDL section is intended to provide a fully generic syntax + // content suitable for most cases (read: if you get errors, then it's quite + // probable that the error is on your side of the .idl setup). + // + // Also, note that the marked-as-generated _i.c file in the Visual Studio + // generator case needs to be referred to as $(IntDir)\foo_i.c at the + // project's file list, otherwise the compiler-side processing won't pick it + // up (for non-directory form, it ends up looking in project binary dir + // only). Perhaps there's something to be done to make this more automatic + // on the CMake side? this->WriteString("<Midl>\n", 2); this->OutputIncludes(includes); this->WriteString("<OutputDirectory>$(IntDir)</OutputDirectory>\n", 3); @@ -1730,3 +1870,12 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() } this->WriteString("</ItemGroup>\n", 1); } + +bool cmVisualStudio10TargetGenerator:: + IsResxHeader(const std::string& headerFile) +{ + std::set<std::string>::iterator it = + this->GeneratorTarget->ExpectedResxHeaders.find(headerFile); + + return it != this->GeneratorTarget->ExpectedResxHeaders.end(); +} diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 55a850a1b..9a480a87f 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -59,9 +59,11 @@ private: void WriteSources(const char* tool, std::vector<cmSourceFile*> const&); void WriteAllSources(); void WriteDotNetReferences(); + void WriteEmbeddedResourceGroup(); void WriteWinRTReferences(); void WritePathAndIncrementalLinkOptions(); void WriteItemDefinitionGroups(); + bool ComputeClOptions(); bool ComputeClOptions(std::string const& configName); void WriteClOptions(std::string const& config, @@ -91,7 +93,7 @@ private: std::vector<cmSourceGroup>& ); void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed, const std::vector<cmSourceGroup>& allGroups); - + bool IsResxHeader(const std::string& headerFile); private: typedef cmVisualStudioGeneratorOptions Options; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 01950e16d..6aca787f5 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -6,6 +6,7 @@ inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s) { std::string ret = s; + cmSystemTools::ReplaceString(ret, ";", "%3B"); cmSystemTools::ReplaceString(ret, "&", "&"); cmSystemTools::ReplaceString(ret, "<", "<"); cmSystemTools::ReplaceString(ret, ">", ">"); @@ -99,13 +100,13 @@ void cmVisualStudioGeneratorOptions::SetVerboseMakefile(bool verbose) } } -bool cmVisualStudioGeneratorOptions::IsDebug() +bool cmVisualStudioGeneratorOptions::IsDebug() const { return this->FlagMap.find("DebugInformationFormat") != this->FlagMap.end(); } //---------------------------------------------------------------------------- -bool cmVisualStudioGeneratorOptions::UsingUnicode() +bool cmVisualStudioGeneratorOptions::UsingUnicode() const { // Look for the a _UNICODE definition. for(std::vector<std::string>::const_iterator di = this->Defines.begin(); @@ -119,7 +120,7 @@ bool cmVisualStudioGeneratorOptions::UsingUnicode() return false; } //---------------------------------------------------------------------------- -bool cmVisualStudioGeneratorOptions::UsingSBCS() +bool cmVisualStudioGeneratorOptions::UsingSBCS() const { // Look for the a _SBCS definition. for(std::vector<std::string>::const_iterator di = this->Defines.begin(); @@ -229,7 +230,7 @@ cmVisualStudioGeneratorOptions } if(this->Version >= cmLocalVisualStudioGenerator::VS10) { - // if there are configuration specifc flags, then + // if there are configuration specific flags, then // use the configuration specific tag for PreprocessorDefinitions if(this->Configuration.size()) { diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index a1a55daff..90f76672d 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -47,10 +47,10 @@ public: void SetVerboseMakefile(bool verbose); // Check for specific options. - bool UsingUnicode(); - bool UsingSBCS(); + bool UsingUnicode() const; + bool UsingSBCS() const; - bool IsDebug(); + bool IsDebug() const; // Write options to output. void OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix, diff --git a/Source/cmVisualStudioSlnData.cxx b/Source/cmVisualStudioSlnData.cxx new file mode 100644 index 000000000..82b4ee84f --- /dev/null +++ b/Source/cmVisualStudioSlnData.cxx @@ -0,0 +1,62 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2013 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmVisualStudioSlnData.h" + +//---------------------------------------------------------------------------- +const cmSlnProjectEntry* +cmSlnData::GetProjectByGUID(const std::string& projectGUID) const +{ + ProjectStorage::const_iterator it(ProjectsByGUID.find(projectGUID)); + if (it != ProjectsByGUID.end()) + return &it->second; + else + return NULL; +} + +//---------------------------------------------------------------------------- +const cmSlnProjectEntry* +cmSlnData::GetProjectByName(const std::string& projectName) const +{ + ProjectStringIndex::const_iterator it(ProjectNameIndex.find(projectName)); + if (it != ProjectNameIndex.end()) + return &it->second->second; + else + return NULL; +} + +//---------------------------------------------------------------------------- +std::vector<cmSlnProjectEntry> cmSlnData::GetProjects() const +{ + ProjectStringIndex::const_iterator it(this->ProjectNameIndex.begin()), + itEnd(this->ProjectNameIndex.end()); + std::vector<cmSlnProjectEntry> result; + for (; it != itEnd; ++it) + result.push_back(it->second->second); + return result; +} + +//---------------------------------------------------------------------------- +cmSlnProjectEntry* cmSlnData::AddProject( + const std::string& projectGUID, + const std::string& projectName, + const std::string& projectRelativePath) +{ + ProjectStorage::iterator it(ProjectsByGUID.find(projectGUID)); + if (it != ProjectsByGUID.end()) + return NULL; + it = ProjectsByGUID.insert( + ProjectStorage::value_type( + projectGUID, + cmSlnProjectEntry(projectGUID, projectName, projectRelativePath))).first; + ProjectNameIndex[projectName] = it; + return &it->second; +} diff --git a/Source/cmVisualStudioSlnData.h b/Source/cmVisualStudioSlnData.h new file mode 100644 index 000000000..ec128cf11 --- /dev/null +++ b/Source/cmVisualStudioSlnData.h @@ -0,0 +1,58 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2013 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmVisualStudioSlnData_h +#define cmVisualStudioSlnData_h + +#include "cmStandardIncludes.h" + +class cmSlnProjectEntry +{ +public: + cmSlnProjectEntry() {} + cmSlnProjectEntry(const std::string& guid, + const std::string& name, + const std::string& relativePath) + : Guid(guid), Name(name), RelativePath(relativePath) + {} + + std::string GetGUID() const { return Guid; } + std::string GetName() const { return Name; } + std::string GetRelativePath() const { return RelativePath; } + +private: + std::string Guid, Name, RelativePath; +}; + + +class cmSlnData +{ +public: + const cmSlnProjectEntry* + GetProjectByGUID(const std::string& projectGUID) const; + + const cmSlnProjectEntry* + GetProjectByName(const std::string& projectName) const; + + std::vector<cmSlnProjectEntry> GetProjects() const; + + cmSlnProjectEntry* AddProject(const std::string& projectGUID, + const std::string& projectName, + const std::string& projectRelativePath); + +private: + typedef std::map<std::string, cmSlnProjectEntry> ProjectStorage; + ProjectStorage ProjectsByGUID; + typedef std::map<std::string, ProjectStorage::iterator> ProjectStringIndex; + ProjectStringIndex ProjectNameIndex; +}; + +#endif diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx new file mode 100644 index 000000000..bae59740a --- /dev/null +++ b/Source/cmVisualStudioSlnParser.cxx @@ -0,0 +1,712 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2013 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmVisualStudioSlnParser.h" + +#include "cmSystemTools.h" +#include "cmVisualStudioSlnData.h" + +#include <cassert> +#include <stack> + +//---------------------------------------------------------------------------- +namespace +{ + enum LineFormat + { + LineMultiValueTag, + LineSingleValueTag, + LineKeyValuePair, + LineVerbatim + }; +} + +//---------------------------------------------------------------------------- +class cmVisualStudioSlnParser::ParsedLine +{ +public: + bool IsComment() const; + bool IsKeyValuePair() const; + + const std::string& GetTag() const { return this->Tag; } + const std::string& GetArg() const { return this->Arg.first; } + std::string GetArgVerbatim() const; + size_t GetValueCount() const { return this->Values.size(); } + const std::string& GetValue(size_t idxValue) const; + std::string GetValueVerbatim(size_t idxValue) const; + + void SetTag(const std::string& tag) { this->Tag = tag; } + void SetArg(const std::string& arg) { this->Arg = StringData(arg, false); } + void SetQuotedArg(const std::string& arg) + { this->Arg = StringData(arg, true); } + void AddValue(const std::string& value) + { this->Values.push_back(StringData(value, false)); } + void AddQuotedValue(const std::string& value) + { this->Values.push_back(StringData(value, true)); } + + void CopyVerbatim(const std::string& line) { this->Tag = line; } + +private: + typedef std::pair<std::string, bool> StringData; + std::string Tag; + StringData Arg; + std::vector<StringData> Values; + static const std::string BadString; + static const std::string Quote; +}; + +//---------------------------------------------------------------------------- +const std::string cmVisualStudioSlnParser::ParsedLine::BadString; +const std::string cmVisualStudioSlnParser::ParsedLine::Quote("\""); + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::ParsedLine::IsComment() const +{ + assert(!this->Tag.empty()); + return (this->Tag[0]== '#'); +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::ParsedLine::IsKeyValuePair() const +{ + assert(!this->Tag.empty()); + return this->Arg.first.empty() && this->Values.size() == 1; +} + +//---------------------------------------------------------------------------- +std::string cmVisualStudioSlnParser::ParsedLine::GetArgVerbatim() const +{ + if (this->Arg.second) + return Quote + this->Arg.first + Quote; + else + return this->Arg.first; +} + +//---------------------------------------------------------------------------- +const std::string& +cmVisualStudioSlnParser::ParsedLine::GetValue(size_t idxValue) const +{ + if (idxValue < this->Values.size()) + return this->Values[idxValue].first; + else + return BadString; +} + +//---------------------------------------------------------------------------- +std::string +cmVisualStudioSlnParser::ParsedLine::GetValueVerbatim(size_t idxValue) const +{ + if (idxValue < this->Values.size()) + { + const StringData& data = this->Values[idxValue]; + if (data.second) + return Quote + data.first + Quote; + else + return data.first; + } + else + return BadString; +} + +//---------------------------------------------------------------------------- +class cmVisualStudioSlnParser::State +{ +public: + explicit State(DataGroupSet requestedData); + + size_t GetCurrentLine() const { return this->CurrentLine; } + bool ReadLine(std::istream& input, std::string& line); + + LineFormat NextLineFormat() const; + + bool Process(const cmVisualStudioSlnParser::ParsedLine& line, + cmSlnData& output, + cmVisualStudioSlnParser::ResultData& result); + + bool Finished(cmVisualStudioSlnParser::ResultData& result); + +private: + enum FileState + { + FileStateStart, + FileStateTopLevel, + FileStateProject, + FileStateProjectDependencies, + FileStateGlobal, + FileStateSolutionConfigurations, + FileStateProjectConfigurations, + FileStateSolutionFilters, + FileStateGlobalSection, + FileStateIgnore + }; + std::stack<FileState> Stack; + std::string EndIgnoreTag; + DataGroupSet RequestedData; + size_t CurrentLine; + + void IgnoreUntilTag(const std::string& endTag); +}; + +//---------------------------------------------------------------------------- +cmVisualStudioSlnParser::State::State(DataGroupSet requestedData) : + RequestedData(requestedData), + CurrentLine(0) +{ + if (this->RequestedData.test(DataGroupProjectDependenciesBit)) + this->RequestedData.set(DataGroupProjectsBit); + this->Stack.push(FileStateStart); +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::State::ReadLine(std::istream& input, + std::string& line) +{ + ++this->CurrentLine; + return !std::getline(input, line).fail(); +} + +//---------------------------------------------------------------------------- +LineFormat cmVisualStudioSlnParser::State::NextLineFormat() const +{ + switch (this->Stack.top()) + { + case FileStateStart: return LineVerbatim; + case FileStateTopLevel: return LineMultiValueTag; + case FileStateProject: return LineSingleValueTag; + case FileStateProjectDependencies: return LineKeyValuePair; + case FileStateGlobal: return LineSingleValueTag; + case FileStateSolutionConfigurations: return LineKeyValuePair; + case FileStateProjectConfigurations: return LineKeyValuePair; + case FileStateSolutionFilters: return LineKeyValuePair; + case FileStateGlobalSection: return LineKeyValuePair; + case FileStateIgnore: return LineVerbatim; + default: + assert(false); + return LineVerbatim; + } +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::State::Process( + const cmVisualStudioSlnParser::ParsedLine& line, + cmSlnData& output, cmVisualStudioSlnParser::ResultData& result) +{ + assert(!line.IsComment()); + switch (this->Stack.top()) + { + case FileStateStart: + if (!cmSystemTools::StringStartsWith( + line.GetTag().c_str(), "Microsoft Visual Studio Solution File")) + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + this->Stack.pop(); + this->Stack.push(FileStateTopLevel); + break; + case FileStateTopLevel: + if (line.GetTag().compare("Project") == 0) + { + if (line.GetValueCount() != 3) + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + if (this->RequestedData.test(DataGroupProjectsBit)) + { + if (!output.AddProject(line.GetValue(2), + line.GetValue(0), + line.GetValue(1))) + { + result.SetError(ResultErrorInputData, this->GetCurrentLine()); + return false; + } + this->Stack.push(FileStateProject); + } + else + this->IgnoreUntilTag("EndProject"); + } + else if (line.GetTag().compare("Global") == 0) + this->Stack.push(FileStateGlobal); + else + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + break; + case FileStateProject: + if (line.GetTag().compare("EndProject") == 0) + this->Stack.pop(); + else if (line.GetTag().compare("ProjectSection") == 0) + { + if (line.GetArg().compare("ProjectDependencies") == 0 && + line.GetValue(0).compare("postProject") == 0) + { + if (this->RequestedData.test(DataGroupProjectDependenciesBit)) + this->Stack.push(FileStateProjectDependencies); + else + this->IgnoreUntilTag("EndProjectSection"); + } + else + this->IgnoreUntilTag("EndProjectSection"); + } + else + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + break; + case FileStateProjectDependencies: + if (line.GetTag().compare("EndProjectSection") == 0) + this->Stack.pop(); + else if (line.IsKeyValuePair()) + // implement dependency storing here, once needed + ; + else + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + break; + case FileStateGlobal: + if (line.GetTag().compare("EndGlobal") == 0) + this->Stack.pop(); + else if (line.GetTag().compare("GlobalSection") == 0) + { + if (line.GetArg().compare("SolutionConfigurationPlatforms") == 0 && + line.GetValue(0).compare("preSolution") == 0) + { + if (this->RequestedData.test(DataGroupSolutionConfigurationsBit)) + this->Stack.push(FileStateSolutionConfigurations); + else + this->IgnoreUntilTag("EndGlobalSection"); + } + else if (line.GetArg().compare("ProjectConfigurationPlatforms") == 0 && + line.GetValue(0).compare("postSolution") == 0) + { + if (this->RequestedData.test(DataGroupProjectConfigurationsBit)) + this->Stack.push(FileStateProjectConfigurations); + else + this->IgnoreUntilTag("EndGlobalSection"); + } + else if (line.GetArg().compare("NestedProjects") == 0 && + line.GetValue(0).compare("preSolution") == 0) + { + if (this->RequestedData.test(DataGroupSolutionFiltersBit)) + this->Stack.push(FileStateSolutionFilters); + else + this->IgnoreUntilTag("EndGlobalSection"); + } + else if (this->RequestedData.test(DataGroupGenericGlobalSectionsBit)) + this->Stack.push(FileStateGlobalSection); + else + this->IgnoreUntilTag("EndGlobalSection"); + } + else + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + break; + case FileStateSolutionConfigurations: + if (line.GetTag().compare("EndGlobalSection") == 0) + this->Stack.pop(); + else if (line.IsKeyValuePair()) + // implement configuration storing here, once needed + ; + else + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + break; + case FileStateProjectConfigurations: + if (line.GetTag().compare("EndGlobalSection") == 0) + this->Stack.pop(); + else if (line.IsKeyValuePair()) + // implement configuration storing here, once needed + ; + else + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + break; + case FileStateSolutionFilters: + if (line.GetTag().compare("EndGlobalSection") == 0) + this->Stack.pop(); + else if (line.IsKeyValuePair()) + // implement filter storing here, once needed + ; + else + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + break; + case FileStateGlobalSection: + if (line.GetTag().compare("EndGlobalSection") == 0) + this->Stack.pop(); + else if (line.IsKeyValuePair()) + // implement section storing here, once needed + ; + else + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + break; + case FileStateIgnore: + if (line.GetTag() == this->EndIgnoreTag) + { + this->Stack.pop(); + this->EndIgnoreTag = ""; + } + break; + default: + result.SetError(ResultErrorBadInternalState, this->GetCurrentLine()); + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::State::Finished( + cmVisualStudioSlnParser::ResultData& result) +{ + if (this->Stack.top() != FileStateTopLevel) + { + result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); + return false; + } + result.Result = ResultOK; + return true; +} + +//---------------------------------------------------------------------------- +void cmVisualStudioSlnParser::State::IgnoreUntilTag(const std::string& endTag) +{ + this->Stack.push(FileStateIgnore); + this->EndIgnoreTag = endTag; +} + +//---------------------------------------------------------------------------- +cmVisualStudioSlnParser::ResultData::ResultData() + : Result(ResultOK) + , ResultLine(0) +{} + +//---------------------------------------------------------------------------- +void cmVisualStudioSlnParser::ResultData::Clear() +{ + *this = ResultData(); +} + +//---------------------------------------------------------------------------- +void cmVisualStudioSlnParser::ResultData::SetError(ParseResult error, + size_t line) +{ + this->Result = error; + this->ResultLine = line; +} + +//---------------------------------------------------------------------------- +const cmVisualStudioSlnParser::DataGroupSet +cmVisualStudioSlnParser::DataGroupProjects( + 1 << cmVisualStudioSlnParser::DataGroupProjectsBit); + +const cmVisualStudioSlnParser::DataGroupSet +cmVisualStudioSlnParser::DataGroupProjectDependencies( + 1 << cmVisualStudioSlnParser::DataGroupProjectDependenciesBit); + +const cmVisualStudioSlnParser::DataGroupSet +cmVisualStudioSlnParser::DataGroupSolutionConfigurations( + 1 << cmVisualStudioSlnParser::DataGroupSolutionConfigurationsBit); + +const cmVisualStudioSlnParser::DataGroupSet +cmVisualStudioSlnParser::DataGroupProjectConfigurations( + 1 << cmVisualStudioSlnParser::DataGroupProjectConfigurationsBit); + +const cmVisualStudioSlnParser::DataGroupSet +cmVisualStudioSlnParser::DataGroupSolutionFilters( + 1 << cmVisualStudioSlnParser::DataGroupSolutionFiltersBit); + +const cmVisualStudioSlnParser::DataGroupSet +cmVisualStudioSlnParser::DataGroupGenericGlobalSections( + 1 << cmVisualStudioSlnParser::DataGroupGenericGlobalSectionsBit); + +const cmVisualStudioSlnParser::DataGroupSet +cmVisualStudioSlnParser::DataGroupAll(~0); + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::Parse(std::istream& input, + cmSlnData& output, + DataGroupSet dataGroups) +{ + this->LastResult.Clear(); + if (!this->IsDataGroupSetSupported(dataGroups)) + { + this->LastResult.SetError(ResultErrorUnsupportedDataGroup, 0); + return false; + } + State state(dataGroups); + return this->ParseImpl(input, output, state); +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::ParseFile(const std::string& file, + cmSlnData& output, + DataGroupSet dataGroups) +{ + this->LastResult.Clear(); + if (!this->IsDataGroupSetSupported(dataGroups)) + { + this->LastResult.SetError(ResultErrorUnsupportedDataGroup, 0); + return false; + } + std::ifstream f(file.c_str()); + if (!f) + { + this->LastResult.SetError(ResultErrorOpeningInput, 0); + return false; + } + State state(dataGroups); + return this->ParseImpl(f, output, state); +} + +//---------------------------------------------------------------------------- +cmVisualStudioSlnParser::ParseResult +cmVisualStudioSlnParser::GetParseResult() const +{ + return this->LastResult.Result; +} + +//---------------------------------------------------------------------------- +size_t cmVisualStudioSlnParser::GetParseResultLine() const +{ + return this->LastResult.ResultLine; +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::GetParseHadBOM() const +{ + return this->LastResult.HadBOM; +} + +//---------------------------------------------------------------------------- +bool +cmVisualStudioSlnParser::IsDataGroupSetSupported(DataGroupSet dataGroups) const +{ + return (dataGroups & DataGroupProjects) == dataGroups; + //only supporting DataGroupProjects for now +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::ParseImpl(std::istream& input, + cmSlnData& output, + State& state) +{ + std::string line; + // Does the .sln start with a Byte Order Mark? + if (!this->ParseBOM(input, line, state)) + return false; + do + { + line = cmSystemTools::TrimWhitespace(line); + if (line.empty()) + continue; + ParsedLine parsedLine; + switch (state.NextLineFormat()) + { + case LineMultiValueTag: + if (!this->ParseMultiValueTag(line, parsedLine, state)) + return false; + break; + case LineSingleValueTag: + if (!this->ParseSingleValueTag(line, parsedLine, state)) + return false; + break; + case LineKeyValuePair: + if (!this->ParseKeyValuePair(line, parsedLine, state)) + return false; + break; + case LineVerbatim: + parsedLine.CopyVerbatim(line); + break; + } + if (parsedLine.IsComment()) + continue; + if (!state.Process(parsedLine, output, this->LastResult)) + return false; + } + while (state.ReadLine(input, line)); + return state.Finished(this->LastResult); +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::ParseBOM(std::istream& input, + std::string& line, + State& state) +{ + char bom[4]; + if (!input.get(bom, 4)) + { + this->LastResult.SetError(ResultErrorReadingInput, 1); + return false; + } + this->LastResult.HadBOM = + (bom[0] == char(0xEF) && bom[1] == char(0xBB) && bom[2] == char(0xBF)); + if (!state.ReadLine(input, line)) + { + this->LastResult.SetError(ResultErrorReadingInput, 1); + return false; + } + if (!this->LastResult.HadBOM) + line = bom + line; // it wasn't a BOM, prepend it to first line + return true; +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::ParseMultiValueTag(const std::string& line, + ParsedLine& parsedLine, + State& state) +{ + size_t idxEqualSign = line.find('='); + const std::string& fullTag = line.substr(0, idxEqualSign); + if (!this->ParseTag(fullTag, parsedLine, state)) + return false; + if (idxEqualSign != line.npos) + { + size_t idxFieldStart = idxEqualSign + 1; + if (idxFieldStart < line.size()) + { + size_t idxParsing = idxFieldStart; + bool inQuotes = false; + for (;;) + { + idxParsing = line.find_first_of(",\"", idxParsing); + bool fieldOver = false; + if (idxParsing == line.npos) + { + fieldOver = true; + if (inQuotes) + { + this->LastResult.SetError(ResultErrorInputStructure, + state.GetCurrentLine()); + return false; + } + } + else if (line[idxParsing] == ',' && !inQuotes) + fieldOver = true; + else if (line[idxParsing] == '"') + inQuotes = !inQuotes; + if (fieldOver) + { + if (!this->ParseValue(line.substr(idxFieldStart, + idxParsing - idxFieldStart), + parsedLine)) + return false; + if (idxParsing == line.npos) + break; //end of last field + idxFieldStart = idxParsing + 1; + } + ++idxParsing; + } + } + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::ParseSingleValueTag(const std::string& line, + ParsedLine& parsedLine, + State& state) +{ + size_t idxEqualSign = line.find('='); + const std::string& fullTag = line.substr(0, idxEqualSign); + if (!this->ParseTag(fullTag, parsedLine, state)) + return false; + if (idxEqualSign != line.npos) + { + if (!this->ParseValue(line.substr(idxEqualSign + 1), parsedLine)) + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::ParseKeyValuePair(const std::string& line, + ParsedLine& parsedLine, + State& /*state*/) +{ + size_t idxEqualSign = line.find('='); + if (idxEqualSign == line.npos) + { + parsedLine.CopyVerbatim(line); + return true; + } + const std::string& key = line.substr(0, idxEqualSign); + parsedLine.SetTag(cmSystemTools::TrimWhitespace(key)); + const std::string& value = line.substr(idxEqualSign + 1); + parsedLine.AddValue(cmSystemTools::TrimWhitespace(value)); + return true; +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag, + ParsedLine& parsedLine, + State& state) +{ + size_t idxLeftParen = fullTag.find('('); + if (idxLeftParen == fullTag.npos) + { + parsedLine.SetTag(cmSystemTools::TrimWhitespace(fullTag)); + return true; + } + parsedLine.SetTag( + cmSystemTools::TrimWhitespace(fullTag.substr(0, idxLeftParen))); + size_t idxRightParen = fullTag.rfind(')'); + if (idxRightParen == fullTag.npos) + { + this->LastResult.SetError(ResultErrorInputStructure, + state.GetCurrentLine()); + return false; + } + const std::string& arg = cmSystemTools::TrimWhitespace( + fullTag.substr(idxLeftParen + 1, idxRightParen - idxLeftParen - 1)); + if (arg[0] == '"') + { + if (arg[arg.size() - 1] != '"') + { + this->LastResult.SetError(ResultErrorInputStructure, + state.GetCurrentLine()); + return false; + } + parsedLine.SetQuotedArg(arg.substr(1, arg.size() - 2)); + } + else + parsedLine.SetArg(arg); + return true; +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioSlnParser::ParseValue(const std::string& value, + ParsedLine& parsedLine) +{ + const std::string& trimmed = cmSystemTools::TrimWhitespace(value); + if (trimmed.empty()) + parsedLine.AddValue(trimmed); + else if (trimmed[0] == '"' && trimmed[trimmed.size() - 1] == '"') + parsedLine.AddQuotedValue(trimmed.substr(1, trimmed.size() - 2)); + else + parsedLine.AddValue(trimmed); + return true; +} diff --git a/Source/cmVisualStudioSlnParser.h b/Source/cmVisualStudioSlnParser.h new file mode 100644 index 000000000..bee70cc13 --- /dev/null +++ b/Source/cmVisualStudioSlnParser.h @@ -0,0 +1,118 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2013 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmVisualStudioSlnParser_h +#define cmVisualStudioSlnParser_h + +#include "cmStandardIncludes.h" + +#include <bitset> + + +class cmSlnData; + + +class cmVisualStudioSlnParser +{ +public: + enum ParseResult + { + ResultOK = 0, + + ResultInternalError = -1, + ResultExternalError = 1, + + ResultErrorOpeningInput = ResultExternalError, + ResultErrorReadingInput, + ResultErrorInputStructure, + ResultErrorInputData, + + ResultErrorBadInternalState = ResultInternalError, + ResultErrorUnsupportedDataGroup = ResultInternalError - 1 + }; + + enum DataGroup + { + DataGroupProjectsBit, + DataGroupProjectDependenciesBit, + DataGroupSolutionConfigurationsBit, + DataGroupProjectConfigurationsBit, + DataGroupSolutionFiltersBit, + DataGroupGenericGlobalSectionsBit, + DataGroupCount + }; + + typedef std::bitset<DataGroupCount> DataGroupSet; + + static const DataGroupSet DataGroupProjects; + static const DataGroupSet DataGroupProjectDependencies; + static const DataGroupSet DataGroupSolutionConfigurations; + static const DataGroupSet DataGroupProjectConfigurations; + static const DataGroupSet DataGroupSolutionFilters; + static const DataGroupSet DataGroupGenericGlobalSections; + static const DataGroupSet DataGroupAll; + + bool Parse(std::istream& input, + cmSlnData& output, + DataGroupSet dataGroups = DataGroupAll); + + bool ParseFile(const std::string& file, + cmSlnData& output, + DataGroupSet dataGroups = DataGroupAll); + + ParseResult GetParseResult() const; + + size_t GetParseResultLine() const; + + bool GetParseHadBOM() const; + +protected: + class State; + friend class State; + class ParsedLine; + + struct ResultData + { + ParseResult Result; + size_t ResultLine; + bool HadBOM; + + ResultData(); + void Clear(); + void SetError(ParseResult error, size_t line); + } LastResult; + + bool IsDataGroupSetSupported(DataGroupSet dataGroups) const; + + bool ParseImpl(std::istream& input, cmSlnData& output, State& state); + + bool ParseBOM(std::istream& input, std::string& line, State& state); + + bool ParseMultiValueTag(const std::string& line, + ParsedLine& parsedLine, + State& state); + + bool ParseSingleValueTag(const std::string& line, + ParsedLine& parsedLine, + State& state); + + bool ParseKeyValuePair(const std::string& line, + ParsedLine& parsedLine, + State& state); + + bool ParseTag(const std::string& fullTag, + ParsedLine& parsedLine, + State& state); + + bool ParseValue(const std::string& value, ParsedLine& parsedLine); +}; + +#endif diff --git a/Source/cmVisualStudioWCEPlatformParser.cxx b/Source/cmVisualStudioWCEPlatformParser.cxx index b302246ea..219a5eb49 100644 --- a/Source/cmVisualStudioWCEPlatformParser.cxx +++ b/Source/cmVisualStudioWCEPlatformParser.cxx @@ -20,8 +20,12 @@ int cmVisualStudioWCEPlatformParser::ParseVersion(const char* version) const std::string vckey = registryBase + "\\Setup\\VC;ProductDir"; const std::string vskey = registryBase + "\\Setup\\VS;ProductDir"; - if(!cmSystemTools::ReadRegistryValue(vckey.c_str(), this->VcInstallDir) || - !cmSystemTools::ReadRegistryValue(vskey.c_str(), this->VsInstallDir)) + if(!cmSystemTools::ReadRegistryValue(vckey.c_str(), + this->VcInstallDir, + cmSystemTools::KeyWOW64_32) || + !cmSystemTools::ReadRegistryValue(vskey.c_str(), + this->VsInstallDir, + cmSystemTools::KeyWOW64_32)) { return 0; } diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 400034582..7d2eeadd6 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -49,9 +49,9 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf, unsigned int i; for(i =0; i < this->Args.size(); ++i) { - err += (this->Args[i].Quoted?"\"":""); + err += (this->Args[i].Delim?"\"":""); err += this->Args[i].Value; - err += (this->Args[i].Quoted?"\"":""); + err += (this->Args[i].Delim?"\"":""); err += " "; } err += "("; diff --git a/Source/cmWin32ProcessExecution.cxx b/Source/cmWin32ProcessExecution.cxx index 5752ab61c..1bdeffbed 100644 --- a/Source/cmWin32ProcessExecution.cxx +++ b/Source/cmWin32ProcessExecution.cxx @@ -506,7 +506,7 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring, /* Create new output read handle and the input write handle. Set * the inheritance properties to FALSE. Otherwise, the child inherits - * the these handles; resulting in non-closeable handles to the pipes + * these handles; resulting in non-closeable handles to the pipes * being created. */ fSuccess = DuplicateHandle(GetCurrentProcess(), this->hChildStdinWr, GetCurrentProcess(), &this->hChildStdinWrDup, 0, diff --git a/Source/cmWin32ProcessExecution.h b/Source/cmWin32ProcessExecution.h index 98b6bda98..2127ebd2e 100644 --- a/Source/cmWin32ProcessExecution.h +++ b/Source/cmWin32ProcessExecution.h @@ -69,7 +69,7 @@ public: /** * Start the process in the directory path. Make sure that the * executable is either in the path or specify the full path. The - * argument verbose specifies wether or not to display output while + * argument verbose specifies whether or not to display output while * it is being generated. */ bool StartProcess(const char*, const char* path, bool verbose); diff --git a/Source/cm_sha2.c b/Source/cm_sha2.c index 12c39ed63..24de2b294 100644 --- a/Source/cm_sha2.c +++ b/Source/cm_sha2.c @@ -740,7 +740,8 @@ void SHA1_Final(sha_byte digest[], SHA_CTX* context) { /* Convert FROM host byte order */ REVERSE64(context->s1.bitcount,context->s1.bitcount); #endif - *(sha_word64*)&context->s1.buffer[56] = context->s1.bitcount; + MEMCPY_BCOPY(&context->s1.buffer[56], &context->s1.bitcount, + sizeof(sha_word64)); /* Final transform: */ SHA1_Internal_Transform(context, (sha_word32*)context->s1.buffer); @@ -1067,7 +1068,8 @@ void SHA256_Internal_Last(SHA_CTX* context) { *context->s256.buffer = 0x80; } /* Set the bit count: */ - *(sha_word64*)&context->s256.buffer[56] = context->s256.bitcount; + MEMCPY_BCOPY(&context->s256.buffer[56], &context->s256.bitcount, + sizeof(sha_word64)); /* Final transform: */ SHA256_Internal_Transform(context, (sha_word32*)context->s256.buffer); @@ -1475,8 +1477,10 @@ void SHA512_Internal_Last(SHA_CTX* context) { *context->s512.buffer = 0x80; } /* Store the length of input data (in bits): */ - *(sha_word64*)&context->s512.buffer[112] = context->s512.bitcount[1]; - *(sha_word64*)&context->s512.buffer[120] = context->s512.bitcount[0]; + MEMCPY_BCOPY(&context->s512.buffer[112], &context->s512.bitcount[1], + sizeof(sha_word64)); + MEMCPY_BCOPY(&context->s512.buffer[120], &context->s512.bitcount[0], + sizeof(sha_word64)); /* Final transform: */ SHA512_Internal_Transform(context, (sha_word64*)context->s512.buffer); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 376758e48..14ddc1b01 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -129,7 +129,7 @@ void cmNeedBackwardsCompatibility(const std::string& variable, "by CMake in versions prior to 1.6. To fix this you might need to set " "the cache value of CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less. If " "you are writing a CMakeLists file, (or have already set " - "CMAKE_BACKWARDS_COMPATABILITY to 1.4 or less) then you probably need " + "CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less) then you probably need " "to include a CMake module to test for the feature this variable " "defines."; cmSystemTools::Error(message.c_str()); @@ -384,11 +384,22 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) cmCacheManager::CacheEntryType type = cmCacheManager::UNINITIALIZED; if(cmCacheManager::ParseEntry(entry.c_str(), var, value, type)) { + // The value is transformed if it is a filepath for example, so + // we can't compare whether the value is already in the cache until + // after we call AddCacheEntry. + const char *cachedValue = + this->CacheManager->GetCacheValue(var.c_str()); + this->CacheManager->AddCacheEntry(var.c_str(), value.c_str(), "No help, variable specified on the command line.", type); if(this->WarnUnusedCli) { - this->WatchUnusedCli(var.c_str()); + if (!cachedValue + || strcmp(this->CacheManager->GetCacheValue(var.c_str()), + cachedValue) != 0) + { + this->WatchUnusedCli(var.c_str()); + } } } else @@ -539,7 +550,7 @@ void cmake::ReadListFile(const std::vector<std::string>& args, } if (!lg->GetMakefile()->ReadListFile(0, path)) { - cmSystemTools::Error("Error processing file:", path); + cmSystemTools::Error("Error processing file: ", path); } } @@ -601,7 +612,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) std::vector<std::string> includeDirs; cmSystemTools::ExpandListArgument(includes, includeDirs); - std::string includeFlags = lg->GetIncludeFlags(includeDirs, + std::string includeFlags = lg->GetIncludeFlags(includeDirs, 0, language.c_str(), false); std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS"); @@ -1158,9 +1169,8 @@ void CMakeCommandUsage(const char* program) << " remove_directory dir - remove a directory and its contents\n" << " rename oldname newname - rename a file or directory " "(on one volume)\n" - << " tar [cxt][vfz][cvfj] file.tar " - "file/dir1 file/dir2 ... - create a tar " - "archive\n" + << " tar [cxt][vfz][cvfj] file.tar [file/dir1 file/dir2 ...]\n" + << " - create or extract a tar or zip archive\n" << " time command [args] ... - run command and return elapsed time\n" << " touch file - touch a file.\n" << " touch_nocreate file - touch a file but do not create it.\n" @@ -1724,10 +1734,11 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args) { return cmake::ExecuteEchoColor(args); } - else if (args[1] == "cmake_automoc") + else if (args[1] == "cmake_automoc" && args.size() >= 4) { cmQtAutomoc automoc; - bool automocSuccess = automoc.Run(args[2].c_str()); + const char *config = args[3].empty() ? 0 : args[3].c_str(); + bool automocSuccess = automoc.Run(args[2].c_str(), config); return automocSuccess ? 0 : 1; } #endif @@ -2367,7 +2378,7 @@ int cmake::ActualConfigure() // EXECUTABLE_OUTPUT_PATH. They are now documented as old-style and // should no longer be used. Therefore we present them only if the // project requires compatibility with CMake 2.4. We detect this - // here by looking for the old CMAKE_BACKWARDS_COMPATABILITY + // here by looking for the old CMAKE_BACKWARDS_COMPATIBILITY // variable created when CMP0001 is not set to NEW. if(this->GetCacheManager()->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY")) { @@ -2633,7 +2644,8 @@ const char* cmake::GetCacheDefinition(const char* name) const void cmake::AddDefaultCommands() { std::list<cmCommand*> commands; - GetBootstrapCommands(commands); + GetBootstrapCommands1(commands); + GetBootstrapCommands2(commands); GetPredefinedCommands(commands); for(std::list<cmCommand*>::iterator i = commands.begin(); i != commands.end(); ++i) @@ -3595,6 +3607,14 @@ void cmake::DefineProperties(cmake *cm) "for the FOLDER target property."); cm->DefineProperty + ("AUTOMOC_TARGETS_FOLDER", cmProperty::GLOBAL, + "Name of FOLDER for *_automoc targets that are added automatically by " + "CMake for targets for which AUTOMOC is enabled.", + "If not set, CMake uses the FOLDER property of the parent target as a " + "default value for this property. See also the documentation for the " + "FOLDER target property and the AUTOMOC target property."); + + cm->DefineProperty ("PREDEFINED_TARGETS_FOLDER", cmProperty::GLOBAL, "Name of FOLDER for targets that are added automatically by CMake.", "If not set, CMake uses \"CMakePredefinedTargets\" as a default " @@ -3647,11 +3667,11 @@ void cmake::RecordPropertyAccess(const char *name, void cmake::ReportUndefinedPropertyAccesses(const char *filename) { + if(!this->GlobalGenerator) + { return; } FILE *progFile = fopen(filename,"w"); - if (!progFile || !this->GlobalGenerator) - { - return; - } + if(!progFile) + { return; } // what are the enabled languages? std::vector<std::string> enLangs; @@ -4049,7 +4069,7 @@ static bool cmakeCheckStampFile(const char* stampName) // TODO: Teach cmGeneratedFileStream to use a random temp file (with // multiple tries in unlikely case of conflict) and use that here. std::ofstream stamp(stampTemp); - stamp << "# CMake generation timestamp file this directory.\n"; + stamp << "# CMake generation timestamp file for this directory.\n"; } if(cmSystemTools::RenameFile(stampTemp, stampName)) { @@ -4121,7 +4141,7 @@ int cmake::WindowsCEEnvironment(const char* version, const std::string& name) return -1; } -// For visual studio 2005 and newer manifest files need to be embeded into +// For visual studio 2005 and newer manifest files need to be embedded into // exe and dll's. This code does that in such a way that incremental linking // still works. int cmake::VisualStudioLink(std::vector<std::string>& args, int type) @@ -4177,7 +4197,7 @@ int cmake::VisualStudioLink(std::vector<std::string>& args, int type) { if(verbose) { - std::cout << "Visual Studio Incremental Link with embeded manifests\n"; + std::cout << "Visual Studio Incremental Link with embedded manifests\n"; } return cmake::VisualStudioLinkIncremental(expandedArgs, type, verbose); } diff --git a/Source/cmake.h b/Source/cmake.h index 63065a17c..a50c1ed02 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -35,7 +35,7 @@ class cmGeneratedFileStream; /** \brief Represents a cmake invocation. * * This class represents a cmake invocation. It is the top level class when - * running cmake. Most cmake based GUIS should primarily create an instance + * running cmake. Most cmake based GUIs should primarily create an instance * of this class and communicate with it. * * The basic process for a GUI is as follows: @@ -255,7 +255,7 @@ class cmake typedef void (*ProgressCallbackType) (const char*msg, float progress, void *); /** - * Set the function used by GUI's to receive progress updates + * Set the function used by GUIs to receive progress updates * Function gets passed: message as a const char*, a progress * amount ranging from 0 to 1.0 and client data. The progress * number provided may be negative in cases where a message is @@ -532,9 +532,9 @@ private: "CMakeCache.txt file, globbing expressions using * and ? are supported. "\ "The option may be repeated for as many cache entries as desired.\n" \ "Use with care, you can make your CMakeCache.txt non-working."}, \ - {"-G <generator-name>", "Specify a makefile generator.", \ + {"-G <generator-name>", "Specify a build system generator.", \ "CMake may support multiple native build systems on certain platforms. " \ - "A makefile generator is responsible for generating a particular build " \ + "A generator is responsible for generating a particular build " \ "system. Possible generator names are specified in the Generators " \ "section."},\ {"-T <toolset-name>", "Specify toolset name if supported by generator.", \ diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 42678419e..68d833964 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -62,7 +62,10 @@ static const char * cmDocumentationDescription[][3] = " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \ " --clean-first = Build target 'clean' first, then build.\n" \ " (To clean only, use --target 'clean'.)\n" \ - " --use-stderr = Don't merge stdout/stderr.\n" \ + " --use-stderr = Don't merge stdout/stderr output and pass the\n" \ + " original stdout/stderr handles to the native\n" \ + " tool so it can use the capabilities of the\n" \ + " calling terminal (e.g. colored output).\n" \ " -- = Pass remaining options to the native tool.\n" //---------------------------------------------------------------------------- @@ -86,8 +89,8 @@ static const char * cmDocumentationOptions[][3] = {"-L[A][H]", "List non-advanced cached variables.", "List cache variables will run CMake and list all the variables from the " "CMake cache that are not marked as INTERNAL or ADVANCED. This will " - "effectively display current CMake settings, which can be then changed " - "with -D option. Changing some of the variable may result in more " + "effectively display current CMake settings, which can then be changed " + "with -D option. Changing some of the variables may result in more " "variables being created. If A is specified, then it will display also " "advanced variables. If H is specified, it will also display help for " "each variable."}, @@ -108,9 +111,11 @@ static const char * cmDocumentationOptions[][3] = "to stdout. This can be used to use cmake instead of pkg-config to find " "installed libraries in plain Makefile-based projects or in " "autoconf-based projects (via share/aclocal/cmake.m4)."}, - {"--graphviz=[file]", "Generate graphviz of dependencies.", + {"--graphviz=[file]", "Generate graphviz of dependencies, see " + "CMakeGraphVizOptions.cmake for more.", "Generate a graphviz input file that will contain all the library and " - "executable dependencies in the project."}, + "executable dependencies in the project. See the documentation for " + "CMakeGraphVizOptions.cmake for more details. "}, {"--system-information [file]", "Dump information about this system.", "Dump a wide range of information about the current system. If run " "from the top of a binary tree for a CMake project it will dump " @@ -152,7 +157,7 @@ static const char * cmDocumentationOptions[][3] = "format is determined depending on the filename suffix. Supported are man " "page, HTML, DocBook and plain text."}, {"--help-commands [file]", "Print help for all commands and exit.", - "Full documentation specific for all current command is displayed." + "Full documentation specific for all current commands is displayed." "If a file is specified, the documentation is written into and the output " "format is determined depending on the filename suffix. Supported are man " "page, HTML, DocBook and plain text."}, @@ -604,7 +609,7 @@ static int do_build(int ac, char** av) } else if(strcmp(av[i], "--use-stderr") == 0) { - outputflag = cmSystemTools::OUTPUT_NORMAL; + outputflag = cmSystemTools::OUTPUT_PASSTHROUGH; } else if(strcmp(av[i], "--") == 0) { diff --git a/Source/cmakewizard.cxx b/Source/cmakewizard.cxx index 749f669d0..bac403a89 100644 --- a/Source/cmakewizard.cxx +++ b/Source/cmakewizard.cxx @@ -28,7 +28,7 @@ void cmakewizard::AskUser(const char* key, printf("Current Value: %s\n", iter.GetValue()); printf("New Value (Enter to keep current value): "); char buffer[4096]; - if(!fgets(buffer, sizeof(buffer)-1, stdin)) + if(!fgets(buffer, static_cast<int>(sizeof(buffer) - 1), stdin)) { buffer[0] = 0; } @@ -67,16 +67,13 @@ bool cmakewizard::AskAdvanced() { printf("Would you like to see advanced options? [No]:"); char buffer[4096]; - if(!fgets(buffer, sizeof(buffer)-1, stdin)) + if(!fgets(buffer, static_cast<int>(sizeof(buffer) - 1), stdin)) { buffer[0] = 0; } - if(buffer[0]) + else if(buffer[0] == 'y' || buffer[0] == 'Y') { - if(buffer[0] == 'y' || buffer[0] == 'Y') - { - return true; - } + return true; } return false; } diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx index 04dab59d0..85715574f 100644 --- a/Source/cmcldeps.cxx +++ b/Source/cmcldeps.cxx @@ -62,8 +62,8 @@ static std::string trimLeadingSpace(const std::string& cmdline) { return cmdline.substr(i); } -static void doEscape(std::string& str, const std::string& search, - const std::string& repl) { +static void replaceAll(std::string& str, const std::string& search, + const std::string& repl) { std::string::size_type pos = 0; while ((pos = str.find(search, pos)) != std::string::npos) { str.replace(pos, search.size(), repl); @@ -71,6 +71,10 @@ static void doEscape(std::string& str, const std::string& search, } } +bool startsWith(const std::string& str, const std::string& what) { + return str.compare(0, what.size(), what) == 0; +} + // Strips one argument from the cmdline and returns it. "surrounding quotes" // are removed from the argument if there were any. static std::string getArg(std::string& cmdline) { @@ -117,6 +121,13 @@ static void parseCommandLine(LPTSTR wincmdline, rest = trimLeadingSpace(cmdline); } +// Not all backslashes need to be escaped in a depfile, but it's easier that +// way. See the re2c grammar in ninja's source code for more info. +static void escapePath(std::string &path) { + replaceAll(path, "\\", "\\\\"); + replaceAll(path, " ", "\\ "); +} + static void outputDepFile(const std::string& dfile, const std::string& objfile, std::vector<std::string>& incs) { @@ -132,16 +143,24 @@ static void outputDepFile(const std::string& dfile, const std::string& objfile, // FIXME should this be fatal or not? delete obj? delete d? if (!out) return; + std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); + replaceAll(cwd, "/", "\\"); + cwd += "\\"; std::string tmp = objfile; - doEscape(tmp, " ", "\\ "); + escapePath(tmp); fprintf(out, "%s: \\\n", tmp.c_str()); std::vector<std::string>::iterator it = incs.begin(); for (; it != incs.end(); ++it) { tmp = *it; - doEscape(tmp, "\\", "/"); - doEscape(tmp, " ", "\\ "); + // The paths need to match the ones used to identify build artifacts in the + // build.ninja file. Therefore we need to canonicalize the path to use + // backward slashes and relativize the path to the build directory. + replaceAll(tmp, "/", "\\"); + if (startsWith(tmp, cwd)) + tmp = tmp.substr(cwd.size()); + escapePath(tmp); fprintf(out, "%s \\\n", tmp.c_str()); } @@ -150,10 +169,6 @@ static void outputDepFile(const std::string& dfile, const std::string& objfile, } -bool startsWith(const std::string& str, const std::string& what) { - return str.compare(0, what.size(), what) == 0; -} - bool contains(const std::string& str, const std::string& what) { return str.find(what) != std::string::npos; } @@ -225,7 +240,7 @@ static int process( const std::string& srcfilename, int main() { - // Use the Win32 api instead of argc/argv so we can avoid interpreting the + // Use the Win32 API instead of argc/argv so we can avoid interpreting the // rest of command line after the .d and .obj. Custom parsing seemed // preferable to the ugliness you get into in trying to re-escape quotes for // subprocesses, so by avoiding argc/argv, the subprocess is called with diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 3e63183eb..e767a1612 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -60,7 +60,7 @@ static const char * cmDocumentationOptions[][3] = "Test output is normally suppressed and only summary information is " "displayed. This option will show even more test output."}, {"--debug", "Displaying more verbose internals of CTest.", - "This feature will result in large number of output that is mostly " + "This feature will result in a large number of output that is mostly " "useful for debugging dashboard problems."}, {"--output-on-failure", "Output anything outputted by the test program " "if the test should fail. This option can also be enabled by setting " @@ -71,7 +71,8 @@ static const char * cmDocumentationOptions[][3] = {"-j <jobs>, --parallel <jobs>", "Run the tests in parallel using the" "given number of jobs.", "This option tells ctest to run the tests in parallel using given " - "number of jobs."}, + "number of jobs. This option can also be set by setting " + "the environment variable CTEST_PARALLEL_LEVEL."}, {"-Q,--quiet", "Make ctest quiet.", "This option will suppress all the output. The output log file will " "still be generated if the --output-log is specified. Options such " @@ -99,7 +100,7 @@ static const char * cmDocumentationOptions[][3] = "This option tells ctest to NOT run the tests whose labels match the " "given regular expression."}, {"-D <dashboard>, --dashboard <dashboard>", "Execute dashboard test", - "This option tells ctest to perform act as a Dart client and perform " + "This option tells ctest to act as a Dart client and perform " "a dashboard test. All tests are <Mode><Test>, where Mode can be " "Experimental, Nightly, and Continuous, and Test can be Start, Update, " "Configure, Build, Test, Coverage, and Submit."}, @@ -171,7 +172,7 @@ static const char * cmDocumentationOptions[][3] = "to this command line are the source and binary directories. By default " "this will run CMake on the Source/Bin directories specified unless " "--build-nocmake is specified. Both --build-makeprogram and " - "--build-generator MUST be provided to use --built-and-test. If " + "--build-generator MUST be provided to use --build-and-test. If " "--test-command is specified then that will be run after the build is " "complete. Other options that affect this mode are --build-target " "--build-nocmake, --build-run-dir, " diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 124b8aca0..0f2783689 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -569,8 +569,17 @@ IF(KWSYS_USE_SystemTools) "Checking whether CXX compiler has unsetenv" DIRECT) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H "Checking whether CXX compiler has environ in stdlib.h" DIRECT) - SET_SOURCE_FILES_PROPERTIES(SystemTools.cxx PROPERTIES - COMPILE_FLAGS "-DKWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV} -DKWSYS_CXX_HAS_UNSETENV=${KWSYS_CXX_HAS_UNSETENV} -DKWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=${KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H}") + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UTIMES + "Checking whether CXX compiler has utimes" DIRECT) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UTIMENSAT + "Checking whether CXX compiler has utimensat" DIRECT) + SET_PROPERTY(SOURCE SystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS + KWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV} + KWSYS_CXX_HAS_UNSETENV=${KWSYS_CXX_HAS_UNSETENV} + KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=${KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H} + KWSYS_CXX_HAS_UTIMES=${KWSYS_CXX_HAS_UTIMES} + KWSYS_CXX_HAS_UTIMENSAT=${KWSYS_CXX_HAS_UTIMENSAT} + ) ENDIF() IF(KWSYS_USE_SystemInformation) @@ -640,6 +649,68 @@ IF(KWSYS_USE_SystemInformation) SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1) ENDIF() + IF(UNIX) + INCLUDE(CheckIncludeFileCXX) + # check for simple stack trace + # usually it's in libc but on FreeBSD + # it's in libexecinfo + FIND_LIBRARY(EXECINFO_LIB "execinfo") + IF (NOT EXECINFO_LIB) + SET(EXECINFO_LIB "") + ENDIF() + CHECK_INCLUDE_FILE_CXX("execinfo.h" KWSYS_CXX_HAS_EXECINFOH) + IF (KWSYS_CXX_HAS_EXECINFOH) + # we have the backtrace header check if it + # can be used with this compiler + SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${EXECINFO_LIB}) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BACKTRACE + "Checking whether backtrace works with this C++ compiler" DIRECT) + SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES) + IF (KWSYS_CXX_HAS_BACKTRACE) + # backtrace is supported by this system and compiler. + # now check for the more advanced capabilities. + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE=1) + # check for symbol lookup using dladdr + CHECK_INCLUDE_FILE_CXX("dlfcn.h" KWSYS_CXX_HAS_DLFCNH) + IF (KWSYS_CXX_HAS_DLFCNH) + # we have symbol lookup libraries and headers + # check if they can be used with this compiler + SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${CMAKE_DL_LIBS}) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_DLADDR + "Checking whether dladdr works with this C++ compiler" DIRECT) + SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES) + IF (KWSYS_CXX_HAS_DLADDR) + # symbol lookup is supported by this system + # and compiler. + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP=1) + ENDIF() + ENDIF() + # c++ demangling support + # check for cxxabi headers + CHECK_INCLUDE_FILE_CXX("cxxabi.h" KWSYS_CXX_HAS_CXXABIH) + IF (KWSYS_CXX_HAS_CXXABIH) + # check if cxxabi can be used with this + # system and compiler. + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CXXABI + "Checking whether cxxabi works with this C++ compiler" DIRECT) + IF (KWSYS_CXX_HAS_CXXABI) + # c++ demangle using cxxabi is supported with + # this system and compiler + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE=1) + ENDIF() + ENDIF() + # basic backtrace works better with release build + # don't bother with advanced features for release + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS_DEBUG KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1) + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS_RELWITHDEBINFO KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1) + ENDIF() + ENDIF() + ENDIF() IF(BORLAND) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM "Checking whether Borland CXX compiler supports assembler instructions" DIRECT) @@ -904,12 +975,23 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) ENDIF(UNIX) ENDIF(KWSYS_USE_DynamicLoader) - IF(KWSYS_USE_SystemInformation AND WIN32) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32) - IF(KWSYS_SYS_HAS_PSAPI) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi) + IF(KWSYS_USE_SystemInformation) + IF(WIN32) + TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32) + IF(KWSYS_SYS_HAS_PSAPI) + TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi) + ENDIF() + ELSEIF(UNIX) + IF (EXECINFO_LIB AND KWSYS_CXX_HAS_BACKTRACE) + # backtrace on FreeBSD is not in libc + TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${EXECINFO_LIB}) + ENDIF() + IF (KWSYS_CXX_HAS_DLADDR) + # for symbol lookup using dladdr + TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS}) + ENDIF() ENDIF() - ENDIF(KWSYS_USE_SystemInformation AND WIN32) + ENDIF() # Apply user-defined target properties to the library. IF(KWSYS_PROPERTIES_CXX) diff --git a/Source/kwsys/CommandLineArguments.hxx.in b/Source/kwsys/CommandLineArguments.hxx.in index 68e9600ef..cbf6ee393 100644 --- a/Source/kwsys/CommandLineArguments.hxx.in +++ b/Source/kwsys/CommandLineArguments.hxx.in @@ -44,7 +44,7 @@ struct CommandLineArgumentsCallbackStructure; * * For the variable interface you associate variable with each argument. When * the argument is specified, the variable is set to the specified value casted - * to the apropriate type. For boolean (NO_ARGUMENT), the value is "1". + * to the appropriate type. For boolean (NO_ARGUMENT), the value is "1". * * Both interfaces can be used at the same time. * @@ -99,7 +99,7 @@ public: STRING_TYPE, // The variable is string (char*) STL_STRING_TYPE, // The variable is string (char*) VECTOR_INT_TYPE, // The variable is integer (int) - VECTOR_BOOL_TYPE, // The vairable is boolean (bool) + VECTOR_BOOL_TYPE, // The variable is boolean (bool) VECTOR_DOUBLE_TYPE, // The variable is float (double) VECTOR_STRING_TYPE, // The variable is string (char*) VECTOR_STL_STRING_TYPE, // The variable is string (char*) @@ -128,7 +128,7 @@ public: void ProcessArgument(const char* arg); /** - * This method will parse arguments and call apropriate methods. + * This method will parse arguments and call appropriate methods. */ int Parse(); @@ -144,7 +144,7 @@ public: /** * Add handler for argument which is going to set the variable to the * specified value. If the argument is specified, the option is casted to the - * apropriate type. + * appropriate type. */ void AddArgument(const char* argument, ArgumentTypeEnum type, bool* variable, const char* help); @@ -160,7 +160,7 @@ public: /** * Add handler for argument which is going to set the variable to the * specified value. If the argument is specified, the option is casted to the - * apropriate type. This will handle the multi argument values. + * appropriate type. This will handle the multi argument values. */ void AddArgument(const char* argument, ArgumentTypeEnum type, kwsys_stl::vector<bool>* variable, const char* help); diff --git a/Source/kwsys/RegularExpression.cxx b/Source/kwsys/RegularExpression.cxx index f6eeebae4..c8297873f 100644 --- a/Source/kwsys/RegularExpression.cxx +++ b/Source/kwsys/RegularExpression.cxx @@ -312,8 +312,8 @@ static char* regbranch (int*); static char* regpiece (int*); static char* regatom (int*); static char* regnode (char); -static const char* regnext (register const char*); -static char* regnext (register char*); +static const char* regnext (const char*); +static char* regnext (char*); static void regc (char); static void reginsert (char, char*); static void regtail (char*, const char*); @@ -344,10 +344,10 @@ static int strcspn (); // for later pattern matching. bool RegularExpression::compile (const char* exp) { - register const char* scan; - register const char* longest; - register size_t len; - int flags; + const char* scan; + const char* longest; + size_t len; + int flags; if (exp == 0) { //RAISE Error, SYM(RegularExpression), SYM(No_Expr), @@ -444,11 +444,11 @@ bool RegularExpression::compile (const char* exp) { * follows makes it hard to avoid. */ static char* reg (int paren, int *flagp) { - register char* ret; - register char* br; - register char* ender; - register int parno =0; - int flags; + char* ret; + char* br; + char* ender; + int parno =0; + int flags; *flagp = HASWIDTH; // Tentatively. @@ -525,10 +525,10 @@ static char* reg (int paren, int *flagp) { * Implements the concatenation operator. */ static char* regbranch (int *flagp) { - register char* ret; - register char* chain; - register char* latest; - int flags; + char* ret; + char* chain; + char* latest; + int flags; *flagp = WORST; // Tentatively. @@ -562,10 +562,10 @@ static char* regbranch (int *flagp) { * endmarker role is not redundant. */ static char* regpiece (int *flagp) { - register char* ret; - register char op; - register char* next; - int flags; + char* ret; + char op; + char* next; + int flags; ret = regatom(&flags); if (ret == 0) @@ -631,8 +631,8 @@ static char* regpiece (int *flagp) { * separate node; the code is simpler that way and it's not worth fixing. */ static char* regatom (int *flagp) { - register char* ret; - int flags; + char* ret; + int flags; *flagp = WORST; // Tentatively. @@ -648,8 +648,8 @@ static char* regatom (int *flagp) { *flagp |= HASWIDTH | SIMPLE; break; case '[':{ - register int rxpclass; - register int rxpclassend; + int rxpclass; + int rxpclassend; if (*regparse == '^') { // Complement of range. ret = regnode(ANYBUT); @@ -720,8 +720,8 @@ static char* regatom (int *flagp) { *flagp |= HASWIDTH | SIMPLE; break; default:{ - register int len; - register char ender; + int len; + char ender; regparse--; len = int(strcspn(regparse, META)); @@ -754,8 +754,8 @@ static char* regatom (int *flagp) { Location. */ static char* regnode (char op) { - register char* ret; - register char* ptr; + char* ret; + char* ptr; ret = regcode; if (ret == ®dummy) { @@ -790,9 +790,9 @@ static void regc (char b) { * Means relocating the operand. */ static void reginsert (char op, char* opnd) { - register char* src; - register char* dst; - register char* place; + char* src; + char* dst; + char* place; if (regcode == ®dummy) { regsize += 3; @@ -816,9 +816,9 @@ static void reginsert (char op, char* opnd) { - regtail - set the next-pointer at the end of a node chain */ static void regtail (char* p, const char* val) { - register char* scan; - register char* temp; - register int offset; + char* scan; + char* temp; + int offset; if (p == ®dummy) return; @@ -893,7 +893,7 @@ bool RegularExpression::find (kwsys_stl::string const& s) // Returns true if found, and sets start and end indexes accordingly. bool RegularExpression::find (const char* string) { - register const char* s; + const char* s; this->searchstring = string; @@ -956,9 +956,9 @@ bool RegularExpression::find (const char* string) { */ static int regtry (const char* string, const char* *start, const char* *end, const char* prog) { - register int i; - register const char* *sp1; - register const char* *ep; + int i; + const char* *sp1; + const char* *ep; reginput = string; regstartp = start; @@ -992,8 +992,8 @@ static int regtry (const char* string, const char* *start, * 0 failure, 1 success */ static int regmatch (const char* prog) { - register const char* scan; // Current node. - const char* next; // Next node. + const char* scan; // Current node. + const char* next; // Next node. scan = prog; @@ -1016,8 +1016,8 @@ static int regmatch (const char* prog) { reginput++; break; case EXACTLY:{ - register size_t len; - register const char* opnd; + size_t len; + const char* opnd; opnd = OPERAND(scan); // Inline the first character, for speed. @@ -1052,8 +1052,8 @@ static int regmatch (const char* prog) { case OPEN + 7: case OPEN + 8: case OPEN + 9:{ - register int no; - register const char* save; + int no; + const char* save; no = OP(scan) - OPEN; save = reginput; @@ -1081,8 +1081,8 @@ static int regmatch (const char* prog) { case CLOSE + 7: case CLOSE + 8: case CLOSE + 9:{ - register int no; - register const char* save; + int no; + const char* save; no = OP(scan) - CLOSE; save = reginput; @@ -1103,7 +1103,7 @@ static int regmatch (const char* prog) { // break; case BRANCH:{ - register const char* save; + const char* save; if (OP(next) != BRANCH) // No choice. next = OPERAND(scan); // Avoid recursion. @@ -1122,10 +1122,10 @@ static int regmatch (const char* prog) { break; case STAR: case PLUS:{ - register char nextch; - register int no; - register const char* save; - register int min_no; + char nextch; + int no; + const char* save; + int min_no; // // Lookahead to avoid useless match attempts when we know @@ -1174,9 +1174,9 @@ static int regmatch (const char* prog) { - regrepeat - repeatedly match something simple, report how many */ static int regrepeat (const char* p) { - register int count = 0; - register const char* scan; - register const char* opnd; + int count = 0; + const char* scan; + const char* opnd; scan = reginput; opnd = OPERAND(p); @@ -1216,8 +1216,8 @@ static int regrepeat (const char* p) { /* - regnext - dig the "next" pointer out of a node */ -static const char* regnext (register const char* p) { - register int offset; +static const char* regnext (const char* p) { + int offset; if (p == ®dummy) return (0); @@ -1232,8 +1232,8 @@ static const char* regnext (register const char* p) { return (p + offset); } -static char* regnext (register char* p) { - register int offset; +static char* regnext (char* p) { + int offset; if (p == ®dummy) return (0); diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in index 8521099ad..8bbc74ac2 100644 --- a/Source/kwsys/SharedForward.h.in +++ b/Source/kwsys/SharedForward.h.in @@ -772,7 +772,7 @@ static int kwsys_shared_forward_get_settings(const char* self_path, const char** dir; for(dir = search_path; *dir; ++dir) { - /* Add seperator between path components. */ + /* Add separator between path components. */ if(dir != search_path) { strcat(ldpath, kwsys_shared_forward_path_sep); diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 9e2a93d7c..beefd7d73 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -18,6 +18,10 @@ # include <winsock.h> // WSADATA, include before sys/types.h #endif +#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif + // TODO: // We need an alternative implementation for many functions in this file // when USE_ASM_INSTRUCTIONS gets defined as 0. @@ -114,8 +118,15 @@ typedef int siginfo_t; # define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN # endif # if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 >= 1050 -# include <execinfo.h> -# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE +# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) +# include <execinfo.h> +# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) +# include <cxxabi.h> +# endif +# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) +# include <dlfcn.h> +# endif +# endif # endif #endif @@ -130,10 +141,13 @@ typedef int siginfo_t; # define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN # endif # endif -# if defined(__GNUC__) +# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) # include <execinfo.h> -# if !(defined(__LSB_VERSION__) && __LSB_VERSION__ < 41) -# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE +# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) +# include <cxxabi.h> +# endif +# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) +# include <dlfcn.h> # endif # endif # if defined(KWSYS_CXX_HAS_RLIMIT64) @@ -357,6 +371,10 @@ public: static void SetStackTraceOnError(int enable); + // get current stack + static + kwsys_stl::string GetProgramStack(int firstFrame, int wholePath); + /** Run the different checks */ void RunCPUCheck(); void RunOSCheck(); @@ -812,6 +830,11 @@ void SystemInformation::SetStackTraceOnError(int enable) SystemInformationImplementation::SetStackTraceOnError(enable); } +kwsys_stl::string SystemInformation::GetProgramStack(int firstFrame, int wholePath) +{ + return SystemInformationImplementation::GetProgramStack(firstFrame, wholePath); +} + /** Run the different checks */ void SystemInformation::RunCPUCheck() { @@ -908,6 +931,12 @@ int LoadLines( } continue; } + char *pBuf=buf; + while(*pBuf) + { + if (*pBuf=='\n') *pBuf='\0'; + pBuf+=1; + } lines.push_back(buf); ++nRead; } @@ -1046,12 +1075,29 @@ void StacktraceSignalHandler( #if defined(__linux) || defined(__APPLE__) kwsys_ios::ostringstream oss; oss + << kwsys_ios::endl << "=========================================================" << kwsys_ios::endl << "Process id " << getpid() << " "; switch (sigNo) { + case SIGINT: + oss << "Caught SIGINT"; + break; + + case SIGTERM: + oss << "Caught SIGTERM"; + break; + + case SIGABRT: + oss << "Caught SIGABRT"; + break; + case SIGFPE: - oss << "Caught SIGFPE "; + oss + << "Caught SIGFPE at " + << (sigInfo->si_addr==0?"0x":"") + << sigInfo->si_addr + << " "; switch (sigInfo->si_code) { # if defined(FPE_INTDIV) @@ -1099,7 +1145,11 @@ void StacktraceSignalHandler( break; case SIGSEGV: - oss << "Caught SIGSEGV "; + oss + << "Caught SIGSEGV at " + << (sigInfo->si_addr==0?"0x":"") + << sigInfo->si_addr + << " "; switch (sigInfo->si_code) { case SEGV_MAPERR: @@ -1116,16 +1166,12 @@ void StacktraceSignalHandler( } break; - case SIGINT: - oss << "Caught SIGTERM"; - break; - - case SIGTERM: - oss << "Caught SIGTERM"; - break; - case SIGBUS: - oss << "Caught SIGBUS type "; + oss + << "Caught SIGBUS at " + << (sigInfo->si_addr==0?"0x":"") + << sigInfo->si_addr + << " "; switch (sigInfo->si_code) { case BUS_ADRALN: @@ -1134,13 +1180,25 @@ void StacktraceSignalHandler( # if defined(BUS_ADRERR) case BUS_ADRERR: - oss << "non-exestent physical address"; + oss << "nonexistent physical address"; break; # endif # if defined(BUS_OBJERR) case BUS_OBJERR: - oss << "object specific hardware error"; + oss << "object-specific hardware error"; + break; +# endif + +# if defined(BUS_MCEERR_AR) + case BUS_MCEERR_AR: + oss << "Hardware memory error consumed on a machine check; action required."; + break; +# endif + +# if defined(BUS_MCEERR_AO) + case BUS_MCEERR_AO: + oss << "Hardware memory error detected in process but not consumed; action optional."; break; # endif @@ -1151,7 +1209,11 @@ void StacktraceSignalHandler( break; case SIGILL: - oss << "Caught SIGILL "; + oss + << "Caught SIGILL at " + << (sigInfo->si_addr==0?"0x":"") + << sigInfo->si_addr + << " "; switch (sigInfo->si_code) { case ILL_ILLOPC: @@ -1205,20 +1267,16 @@ void StacktraceSignalHandler( oss << "Caught " << sigNo << " code " << sigInfo->si_code; break; } - oss << kwsys_ios::endl; -#if defined(KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE) - oss << "Program Stack:" << kwsys_ios::endl; - void *stackSymbols[128]; - int n=backtrace(stackSymbols,128); - char **stackText=backtrace_symbols(stackSymbols,n); - for (int i=0; i<n; ++i) - { - oss << " " << stackText[i] << kwsys_ios::endl; - } -#endif oss - << "=========================================================" << kwsys_ios::endl; + << kwsys_ios::endl + << "Program Stack:" << kwsys_ios::endl + << SystemInformationImplementation::GetProgramStack(2,0) + << "=========================================================" << kwsys_ios::endl; kwsys_ios::cerr << oss.str() << kwsys_ios::endl; + + // restore the previously registered handlers + // and abort + SystemInformationImplementation::SetStackTraceOnError(0); abort(); #else // avoid warning C4100 @@ -1227,8 +1285,213 @@ void StacktraceSignalHandler( #endif } #endif + +#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) +#define safes(_arg)((_arg)?(_arg):"???") + +// Description: +// A container for symbol properties. Each instance +// must be Initialized. +class SymbolProperties +{ +public: + SymbolProperties(); + + // Description: + // The SymbolProperties instance must be initialized by + // passing a stack address. + void Initialize(void *address); + + // Description: + // Get the symbol's stack address. + void *GetAddress() const { return this->Address; } + + // Description: + // If not set paths will be removed. eg, from a binary + // or source file. + void SetReportPath(int rp){ this->ReportPath=rp; } + + // Description: + // Set/Get the name of the binary file that the symbol + // is found in. + void SetBinary(const char *binary) + { this->Binary=safes(binary); } + + kwsys_stl::string GetBinary() const; + + // Description: + // Set the name of the function that the symbol is found in. + // If c++ demangling is supported it will be demangled. + void SetFunction(const char *function) + { this->Function=this->Demangle(function); } + + kwsys_stl::string GetFunction() const + { return this->Function; } + + // Description: + // Set/Get the name of the source file where the symbol + // is defined. + void SetSourceFile(const char *sourcefile) + { this->SourceFile=safes(sourcefile); } + + kwsys_stl::string GetSourceFile() const + { return this->GetFileName(this->SourceFile); } + + // Description: + // Set/Get the line number where the symbol is defined + void SetLineNumber(long linenumber){ this->LineNumber=linenumber; } + long GetLineNumber() const { return this->LineNumber; } + + // Description: + // Set the address where the biinary image is mapped + // into memory. + void SetBinaryBaseAddress(void *address) + { this->BinaryBaseAddress=address; } + +private: + void *GetRealAddress() const + { return (void*)((char*)this->Address-(char*)this->BinaryBaseAddress); } + + kwsys_stl::string GetFileName(const kwsys_stl::string &path) const; + kwsys_stl::string Demangle(const char *symbol) const; + +private: + kwsys_stl::string Binary; + void *BinaryBaseAddress; + void *Address; + kwsys_stl::string SourceFile; + kwsys_stl::string Function; + long LineNumber; + int ReportPath; +}; + +// -------------------------------------------------------------------------- +kwsys_ios::ostream &operator<<( + kwsys_ios::ostream &os, + const SymbolProperties &sp) +{ +#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) + os + << kwsys_ios::hex << sp.GetAddress() << " : " + << sp.GetFunction() + << " [(" << sp.GetBinary() << ") " + << sp.GetSourceFile() << ":" + << kwsys_ios::dec << sp.GetLineNumber() << "]"; +#elif defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) + void *addr = sp.GetAddress(); + char **syminfo = backtrace_symbols(&addr,1); + os << safes(syminfo[0]); + free(syminfo); +#else + (void)os; + (void)sp; +#endif + return os; +} + +// -------------------------------------------------------------------------- +SymbolProperties::SymbolProperties() +{ + // not using an initializer list + // to avoid some PGI compiler warnings + this->SetBinary("???"); + this->SetBinaryBaseAddress(NULL); + this->Address = NULL; + this->SetSourceFile("???"); + this->SetFunction("???"); + this->SetLineNumber(-1); + this->SetReportPath(0); + // avoid PGI compiler warnings + this->GetRealAddress(); + this->GetFunction(); + this->GetSourceFile(); + this->GetLineNumber(); +} + +// -------------------------------------------------------------------------- +kwsys_stl::string SymbolProperties::GetFileName(const kwsys_stl::string &path) const +{ + kwsys_stl::string file(path); + if (!this->ReportPath) + { + size_t at = file.rfind("/"); + if (at!=kwsys_stl::string::npos) + { + file = file.substr(at+1,kwsys_stl::string::npos); + } + } + return file; +} + +// -------------------------------------------------------------------------- +kwsys_stl::string SymbolProperties::GetBinary() const +{ +// only linux has proc fs +#if defined(__linux__) + if (this->Binary=="/proc/self/exe") + { + kwsys_stl::string binary; + char buf[1024]={'\0'}; + ssize_t ll=0; + if ((ll=readlink("/proc/self/exe",buf,1024))>0) + { + buf[ll]='\0'; + binary=buf; + } + else + { + binary="/proc/self/exe"; + } + return this->GetFileName(binary); + } +#endif + return this->GetFileName(this->Binary); +} + +// -------------------------------------------------------------------------- +kwsys_stl::string SymbolProperties::Demangle(const char *symbol) const +{ + kwsys_stl::string result = safes(symbol); +#if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) + int status = 0; + size_t bufferLen = 1024; + char *buffer = (char*)malloc(1024); + char *demangledSymbol = + abi::__cxa_demangle(symbol, buffer, &bufferLen, &status); + if (!status) + { + result = demangledSymbol; + } + free(buffer); +#else + (void)symbol; +#endif + return result; +} + +// -------------------------------------------------------------------------- +void SymbolProperties::Initialize(void *address) +{ + this->Address = address; +#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) + // first fallback option can demangle c++ functions + Dl_info info; + int ierr=dladdr(this->Address,&info); + if (ierr && info.dli_sname && info.dli_saddr) + { + this->SetBinary(info.dli_fname); + this->SetFunction(info.dli_sname); + } +#else + // second fallback use builtin backtrace_symbols + // to decode the bactrace. +#endif +} +#endif // don't define this class if we're not using it + } // anonymous namespace + SystemInformationImplementation::SystemInformationImplementation() { this->TotalVirtualMemory = 0; @@ -1471,7 +1734,7 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName( { char host[NI_MAXHOST]={'\0'}; - int addrlen + socklen_t addrlen = (fam==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6)); ierr=getnameinfo( @@ -3336,12 +3599,61 @@ SystemInformationImplementation::GetProcessId() } /** +return current program stack in a string +demangle cxx symbols if possible. +*/ +kwsys_stl::string SystemInformationImplementation::GetProgramStack( + int firstFrame, + int wholePath) +{ + kwsys_stl::string programStack = "" +#if !defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) + "WARNING: The stack could not be examined " + "because backtrace is not supported.\n" +#elif !defined(KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD) + "WARNING: The stack trace will not use advanced " + "capabilities because this is a release build.\n" +#else +# if !defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) + "WARNING: Function names will not be demangled because " + "dladdr is not available.\n" +# endif +# if !defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) + "WARNING: Function names will not be demangled " + "because cxxabi is not available.\n" +# endif +#endif + ; + + kwsys_ios::ostringstream oss; +#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) + void *stackSymbols[256]; + int nFrames=backtrace(stackSymbols,256); + for (int i=firstFrame; i<nFrames; ++i) + { + SymbolProperties symProps; + symProps.SetReportPath(wholePath); + symProps.Initialize(stackSymbols[i]); + oss << symProps << kwsys_ios::endl; + } +#else + (void)firstFrame; + (void)wholePath; +#endif + programStack += oss.str(); + + return programStack; +} + + +/** when set print stack trace in response to common signals. */ void SystemInformationImplementation::SetStackTraceOnError(int enable) { #if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) static int saOrigValid=0; + static struct sigaction saABRTOrig; static struct sigaction saSEGVOrig; static struct sigaction saTERMOrig; static struct sigaction saINTOrig; @@ -3349,9 +3661,11 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable) static struct sigaction saBUSOrig; static struct sigaction saFPEOrig; + if (enable && !saOrigValid) { // save the current actions + sigaction(SIGABRT,0,&saABRTOrig); sigaction(SIGSEGV,0,&saSEGVOrig); sigaction(SIGTERM,0,&saTERMOrig); sigaction(SIGINT,0,&saINTOrig); @@ -3365,9 +3679,10 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable) // install ours struct sigaction sa; sa.sa_sigaction=(SigAction)StacktraceSignalHandler; - sa.sa_flags=SA_SIGINFO|SA_RESTART; + sa.sa_flags=SA_SIGINFO|SA_RESTART|SA_RESETHAND; sigemptyset(&sa.sa_mask); + sigaction(SIGABRT,&sa,0); sigaction(SIGSEGV,&sa,0); sigaction(SIGTERM,&sa,0); sigaction(SIGINT,&sa,0); @@ -3379,6 +3694,7 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable) if (!enable && saOrigValid) { // restore previous actions + sigaction(SIGABRT,&saABRTOrig,0); sigaction(SIGSEGV,&saSEGVOrig,0); sigaction(SIGTERM,&saTERMOrig,0); sigaction(SIGINT,&saINTOrig,0); @@ -3487,7 +3803,7 @@ bool SystemInformationImplementation::QueryLinuxMemory() bool have[6] = { false, false, false, false, false, false }; unsigned long value[6]; int count = 0; - while(fgets(buffer, sizeof(buffer), fd)) + while(fgets(buffer, static_cast<int>(sizeof(buffer)), fd)) { for(int i=0; i < 6; ++i) { diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in index 8f4cb4e5a..a9fd05def 100644 --- a/Source/kwsys/SystemInformation.hxx.in +++ b/Source/kwsys/SystemInformation.hxx.in @@ -117,8 +117,8 @@ public: // Get total system RAM in units of KiB available to this process. // This may differ from the host available if a per-process resource // limit is applied. per-process memory limits are applied on unix - // system via rlimit api. Resource limits that are not imposed via - // rlimit api may be reported to us via an application specified + // system via rlimit API. Resource limits that are not imposed via + // rlimit API may be reported to us via an application specified // environment variable. LongLong GetProcMemoryAvailable( const char *hostLimitEnvVarName=NULL, @@ -136,6 +136,12 @@ public: static void SetStackTraceOnError(int enable); + // format and return the current program stack in a string. In + // order to produce an informative stack trace the application + // should be dynamically linked and compiled with debug symbols. + static + kwsys_stl::string GetProgramStack(int firstFrame, int wholePath); + /** Run the different checks */ void RunCPUCheck(); void RunOSCheck(); diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 8b25d608d..e9a1fd37d 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -605,7 +605,7 @@ bool SystemTools::MakeDirectory(const char* path) } if(SystemTools::FileExists(path)) { - return true; + return SystemTools::FileIsDirectory(path); } kwsys_stl::string dir = path; if(dir.size() == 0) @@ -695,6 +695,52 @@ void SystemTools::ReplaceString(kwsys_stl::string& source, #endif #if defined(_WIN32) && !defined(__CYGWIN__) +static bool SystemToolsParseRegistryKey(const char* key, + HKEY& primaryKey, + kwsys_stl::string& second, + kwsys_stl::string& valuename) +{ + kwsys_stl::string primary = key; + + size_t start = primary.find("\\"); + if (start == kwsys_stl::string::npos) + { + return false; + } + + size_t valuenamepos = primary.find(";"); + if (valuenamepos != kwsys_stl::string::npos) + { + valuename = primary.substr(valuenamepos+1); + } + + second = primary.substr(start+1, valuenamepos-start-1); + primary = primary.substr(0, start); + + if (primary == "HKEY_CURRENT_USER") + { + primaryKey = HKEY_CURRENT_USER; + } + if (primary == "HKEY_CURRENT_CONFIG") + { + primaryKey = HKEY_CURRENT_CONFIG; + } + if (primary == "HKEY_CLASSES_ROOT") + { + primaryKey = HKEY_CLASSES_ROOT; + } + if (primary == "HKEY_LOCAL_MACHINE") + { + primaryKey = HKEY_LOCAL_MACHINE; + } + if (primary == "HKEY_USERS") + { + primaryKey = HKEY_USERS; + } + + return true; +} + static DWORD SystemToolsMakeRegistryMode(DWORD mode, SystemTools::KeyWOW64 view) { @@ -718,6 +764,55 @@ static DWORD SystemToolsMakeRegistryMode(DWORD mode, } #endif +#if defined(_WIN32) && !defined(__CYGWIN__) +bool +SystemTools::GetRegistrySubKeys(const char *key, + kwsys_stl::vector<kwsys_stl::string>& subkeys, + KeyWOW64 view) +{ + HKEY primaryKey = HKEY_CURRENT_USER; + kwsys_stl::string second; + kwsys_stl::string valuename; + if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) + { + return false; + } + + HKEY hKey; + if(RegOpenKeyEx(primaryKey, + second.c_str(), + 0, + SystemToolsMakeRegistryMode(KEY_READ, view), + &hKey) != ERROR_SUCCESS) + { + return false; + } + else + { + char name[1024]; + DWORD dwNameSize = sizeof(name)/sizeof(name[0]); + + DWORD i = 0; + while (RegEnumKey(hKey, i, name, dwNameSize) == ERROR_SUCCESS) + { + subkeys.push_back(name); + ++i; + } + + RegCloseKey(hKey); + } + + return true; +} +#else +bool SystemTools::GetRegistrySubKeys(const char *, + kwsys_stl::vector<kwsys_stl::string>&, + KeyWOW64) +{ + return false; +} +#endif + // Read a registry value. // Example : // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath @@ -730,47 +825,14 @@ bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value, KeyWOW64 view) { bool valueset = false; - kwsys_stl::string primary = key; + HKEY primaryKey = HKEY_CURRENT_USER; kwsys_stl::string second; kwsys_stl::string valuename; - - size_t start = primary.find("\\"); - if (start == kwsys_stl::string::npos) + if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { return false; } - size_t valuenamepos = primary.find(";"); - if (valuenamepos != kwsys_stl::string::npos) - { - valuename = primary.substr(valuenamepos+1); - } - - second = primary.substr(start+1, valuenamepos-start-1); - primary = primary.substr(0, start); - - HKEY primaryKey = HKEY_CURRENT_USER; - if (primary == "HKEY_CURRENT_USER") - { - primaryKey = HKEY_CURRENT_USER; - } - if (primary == "HKEY_CURRENT_CONFIG") - { - primaryKey = HKEY_CURRENT_CONFIG; - } - if (primary == "HKEY_CLASSES_ROOT") - { - primaryKey = HKEY_CLASSES_ROOT; - } - if (primary == "HKEY_LOCAL_MACHINE") - { - primaryKey = HKEY_LOCAL_MACHINE; - } - if (primary == "HKEY_USERS") - { - primaryKey = HKEY_USERS; - } - HKEY hKey; if(RegOpenKeyEx(primaryKey, second.c_str(), @@ -834,47 +896,14 @@ bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &, bool SystemTools::WriteRegistryValue(const char *key, const char *value, KeyWOW64 view) { - kwsys_stl::string primary = key; + HKEY primaryKey = HKEY_CURRENT_USER; kwsys_stl::string second; kwsys_stl::string valuename; - - size_t start = primary.find("\\"); - if (start == kwsys_stl::string::npos) + if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { return false; } - size_t valuenamepos = primary.find(";"); - if (valuenamepos != kwsys_stl::string::npos) - { - valuename = primary.substr(valuenamepos+1); - } - - second = primary.substr(start+1, valuenamepos-start-1); - primary = primary.substr(0, start); - - HKEY primaryKey = HKEY_CURRENT_USER; - if (primary == "HKEY_CURRENT_USER") - { - primaryKey = HKEY_CURRENT_USER; - } - if (primary == "HKEY_CURRENT_CONFIG") - { - primaryKey = HKEY_CURRENT_CONFIG; - } - if (primary == "HKEY_CLASSES_ROOT") - { - primaryKey = HKEY_CLASSES_ROOT; - } - if (primary == "HKEY_LOCAL_MACHINE") - { - primaryKey = HKEY_LOCAL_MACHINE; - } - if (primary == "HKEY_USERS") - { - primaryKey = HKEY_USERS; - } - HKEY hKey; DWORD dwDummy; char lpClass[] = ""; @@ -919,47 +948,14 @@ bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64) #if defined(_WIN32) && !defined(__CYGWIN__) bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view) { - kwsys_stl::string primary = key; + HKEY primaryKey = HKEY_CURRENT_USER; kwsys_stl::string second; kwsys_stl::string valuename; - - size_t start = primary.find("\\"); - if (start == kwsys_stl::string::npos) + if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { return false; } - size_t valuenamepos = primary.find(";"); - if (valuenamepos != kwsys_stl::string::npos) - { - valuename = primary.substr(valuenamepos+1); - } - - second = primary.substr(start+1, valuenamepos-start-1); - primary = primary.substr(0, start); - - HKEY primaryKey = HKEY_CURRENT_USER; - if (primary == "HKEY_CURRENT_USER") - { - primaryKey = HKEY_CURRENT_USER; - } - if (primary == "HKEY_CURRENT_CONFIG") - { - primaryKey = HKEY_CURRENT_CONFIG; - } - if (primary == "HKEY_CLASSES_ROOT") - { - primaryKey = HKEY_CLASSES_ROOT; - } - if (primary == "HKEY_LOCAL_MACHINE") - { - primaryKey = HKEY_LOCAL_MACHINE; - } - if (primary == "HKEY_USERS") - { - primaryKey = HKEY_USERS; - } - HKEY hKey; if(RegOpenKeyEx(primaryKey, second.c_str(), @@ -1124,22 +1120,58 @@ bool SystemTools::Touch(const char* filename, bool create) } return false; } -#ifdef _MSC_VER -#define utime _utime -#define utimbuf _utimbuf -#endif - struct stat fromStat; - if(stat(filename, &fromStat) < 0) +#if defined(_WIN32) && !defined(__CYGWIN__) + HANDLE h = CreateFile(filename, FILE_WRITE_ATTRIBUTES, + FILE_SHARE_WRITE, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0); + if(!h) + { + return false; + } + FILETIME mtime; + GetSystemTimeAsFileTime(&mtime); + if(!SetFileTime(h, 0, 0, &mtime)) + { + CloseHandle(h); + return false; + } + CloseHandle(h); +#elif KWSYS_CXX_HAS_UTIMENSAT + struct timespec times[2] = {{0,UTIME_OMIT},{0,UTIME_NOW}}; + if(utimensat(AT_FDCWD, filename, times, 0) < 0) + { + return false; + } +#else + struct stat st; + if(stat(filename, &st) < 0) { return false; } - struct utimbuf buf; - buf.actime = fromStat.st_atime; - buf.modtime = static_cast<time_t>(SystemTools::GetTime()); - if(utime(filename, &buf) < 0) + struct timeval mtime; + gettimeofday(&mtime, 0); +# if KWSYS_CXX_HAS_UTIMES + struct timeval times[2] = + { +# if KWSYS_STAT_HAS_ST_MTIM + {st.st_atim.tv_sec, st.st_atim.tv_nsec/1000}, /* tv_sec, tv_usec */ +# else + {st.st_atime, 0}, +# endif + mtime + }; + if(utimes(filename, times) < 0) + { + return false; + } +# else + struct utimbuf times = {st.st_atime, mtime.tv_sec}; + if(utime(filename, ×) < 0) { return false; } +# endif +#endif return true; } @@ -2741,12 +2773,12 @@ bool SystemTools::FileIsDirectory(const char* name) return false; } - // Remove any trailing slash from the name. + // Remove any trailing slash from the name except in a root component. char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH]; std::string string_buffer; size_t last = length-1; if(last > 0 && (name[last] == '/' || name[last] == '\\') - && strcmp(name, "/") !=0) + && strcmp(name, "/") !=0 && name[last-1] != ':') { if(last < sizeof(local_buffer)) { @@ -3049,7 +3081,7 @@ SystemToolsAppendComponents( { if(*i == "..") { - if(out_components.begin() != out_components.end()) + if(out_components.size() > 1) { out_components.erase(out_components.end()-1, out_components.end()); } @@ -4011,7 +4043,7 @@ void SystemTools::SplitProgramFromArgs(const char* path, args = dir.substr(spacePos, dir.size()-spacePos); return; } - // Now try and find the the program in the path + // Now try and find the program in the path findProg = SystemTools::FindProgram(tryProg.c_str(), e); if(findProg.size()) { @@ -4225,17 +4257,13 @@ bool SystemTools::IsSubDirectory(const char* cSubdir, const char* cDir) } kwsys_stl::string subdir = cSubdir; kwsys_stl::string dir = cDir; + SystemTools::ConvertToUnixSlashes(subdir); SystemTools::ConvertToUnixSlashes(dir); - kwsys_stl::string path = subdir; - do + if(subdir.size() > dir.size() && subdir[dir.size()] == '/') { - path = SystemTools::GetParentDirectory(path.c_str()); - if(SystemTools::ComparePath(dir.c_str(), path.c_str())) - { - return true; - } + std::string s = subdir.substr(0, dir.size()); + return SystemTools::ComparePath(s.c_str(), dir.c_str()); } - while ( path.size() > dir.size() ); return false; } @@ -4837,7 +4865,8 @@ static int SystemToolsDebugReport(int, char* message, int*) void SystemTools::EnableMSVCDebugHook() { - if (getenv("DART_TEST_FROM_DART")) + if (getenv("DART_TEST_FROM_DART") || + getenv("DASHBOARD_TEST_FROM_CTEST")) { _CrtSetReportHook(SystemToolsDebugReport); } diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 9c56e96b0..d6dae3986 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -716,6 +716,13 @@ public: enum KeyWOW64 { KeyWOW64_Default, KeyWOW64_32, KeyWOW64_64 }; /** + * Get a list of subkeys. + */ + static bool GetRegistrySubKeys(const char *key, + kwsys_stl::vector<kwsys_stl::string>& subkeys, + KeyWOW64 view = KeyWOW64_Default); + + /** * Read a registry value */ static bool ReadRegistryValue(const char *key, kwsys_stl::string &value, @@ -766,7 +773,7 @@ public: static kwsys_stl::string GetCurrentWorkingDirectory(bool collapse =true); /** - * Change directory the the directory specified + * Change directory to the directory specified */ static int ChangeDirectory(const char* dir); diff --git a/Source/kwsys/auto_ptr.hxx.in b/Source/kwsys/auto_ptr.hxx.in index 857b1db3c..ad9654cb4 100644 --- a/Source/kwsys/auto_ptr.hxx.in +++ b/Source/kwsys/auto_ptr.hxx.in @@ -31,6 +31,17 @@ # define @KWSYS_NAMESPACE@_AUTO_PTR_CAST(a) a #endif +// In C++11, clang will warn about using dynamic exception specifications +// as they are deprecated. But as this class is trying to faithfully +// mimic std::auto_ptr, we want to keep the 'throw()' decorations below. +// So we suppress the warning. +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated") +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated" +# endif +#endif + namespace @KWSYS_NAMESPACE@ { @@ -198,4 +209,11 @@ public: } // namespace @KWSYS_NAMESPACE@ +// Undo warning suppression. +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated") +# pragma clang diagnostic pop +# endif +#endif + #endif diff --git a/Source/kwsys/hashtable.hxx.in b/Source/kwsys/hashtable.hxx.in index c83550304..651de82bf 100644 --- a/Source/kwsys/hashtable.hxx.in +++ b/Source/kwsys/hashtable.hxx.in @@ -62,6 +62,17 @@ # pragma set woff 3970 /* pointer to int conversion */ 3321 3968 #endif +// In C++11, clang will warn about using dynamic exception specifications +// as they are deprecated. But as this class is trying to faithfully +// mimic unordered_set and unordered_map, we want to keep the 'throw()' +// decorations below. So we suppress the warning. +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated") +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated" +# endif +#endif + #if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE # define @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(T) @KWSYS_NAMESPACE@_stl::allocator< T > #elif @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE @@ -1268,6 +1279,13 @@ using @KWSYS_NAMESPACE@::operator==; using @KWSYS_NAMESPACE@::operator!=; #endif +// Undo warning suppression. +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated") +# pragma clang diagnostic pop +# endif +#endif + #if defined(_MSC_VER) # pragma warning (pop) #endif diff --git a/Source/kwsys/kwsysPlatformTests.cmake b/Source/kwsys/kwsysPlatformTests.cmake index d042450ee..f9ee254f0 100644 --- a/Source/kwsys/kwsysPlatformTests.cmake +++ b/Source/kwsys/kwsysPlatformTests.cmake @@ -19,6 +19,7 @@ MACRO(KWSYS_PLATFORM_TEST lang var description invert) ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}} COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_TEST_DEFINES} ${KWSYS_PLATFORM_TEST_EXTRA_FLAGS} + CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${KWSYS_PLATFORM_TEST_LINK_LIBRARIES}" OUTPUT_VARIABLE OUTPUT) IF(${var}_COMPILED) FILE(APPEND @@ -150,9 +151,11 @@ ENDMACRO(KWSYS_PLATFORM_C_TEST_RUN) MACRO(KWSYS_PLATFORM_CXX_TEST var description invert) SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES}) SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS}) + SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES ${KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES}) KWSYS_PLATFORM_TEST(CXX "${var}" "${description}" "${invert}") SET(KWSYS_PLATFORM_TEST_DEFINES) SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) + SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES) ENDMACRO(KWSYS_PLATFORM_CXX_TEST) MACRO(KWSYS_PLATFORM_CXX_TEST_RUN var description invert) diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx index 48976c442..be7a09ee2 100644 --- a/Source/kwsys/kwsysPlatformTestsCXX.cxx +++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx @@ -494,6 +494,73 @@ int main() } #endif +#ifdef TEST_KWSYS_CXX_HAS_UTIMES +#include <sys/time.h> +int main() +{ + struct timeval* current_time = 0; + return utimes("/example", current_time); +} +#endif + +#ifdef TEST_KWSYS_CXX_HAS_UTIMENSAT +#include <fcntl.h> +#include <sys/stat.h> +int main() +{ + struct timespec times[2] = {{0,UTIME_OMIT},{0,UTIME_NOW}}; + return utimensat(AT_FDCWD, "/example", times, AT_SYMLINK_NOFOLLOW); +} +#endif + +#ifdef TEST_KWSYS_CXX_HAS_BACKTRACE +#if defined(__PATHSCALE__) || defined(__PATHCC__) \ + || (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41)) +backtrace doesnt work with this compiler or os +#endif +#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif +#include <execinfo.h> +int main() +{ + void *stackSymbols[256]; + backtrace(stackSymbols,256); + backtrace_symbols(&stackSymbols[0],1); + return 0; +} +#endif + +#ifdef TEST_KWSYS_CXX_HAS_DLADDR +#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif +#include <dlfcn.h> +int main() +{ + Dl_info info; + int ierr=dladdr((void*)main,&info); + return 0; +} +#endif + +#ifdef TEST_KWSYS_CXX_HAS_CXXABI +#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif +#include <cxxabi.h> +int main() +{ + int status = 0; + size_t bufferLen = 512; + char buffer[512] = {'\0'}; + const char *function="_ZN5kwsys17SystemInformation15GetProgramStackEii"; + char *demangledFunction = + abi::__cxa_demangle(function, buffer, &bufferLen, &status); + return status; +} +#endif + #ifdef TEST_KWSYS_CXX_TYPE_INFO /* Collect fundamental type information and save it to a CMake script. */ diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx index 61c157291..dd6d60390 100644 --- a/Source/kwsys/testDynamicLoader.cxx +++ b/Source/kwsys/testDynamicLoader.cxx @@ -109,9 +109,9 @@ int testDynamicLoader(int argc, char *argv[]) // dlopen() on Syllable before 11/22/2007 doesn't return 0 on error #ifndef __SYLLABLE__ - // Make sure that inexistant lib is giving correct result + // Make sure that inexistent lib is giving correct result res += TestDynamicLoader("azerty_", "foo_bar",0,0,0); - // Make sure that random binary file cannnot be assimilated as dylib + // Make sure that random binary file cannot be assimilated as dylib res += TestDynamicLoader(TEST_SYSTEMTOOLS_BIN_FILE, "wp",0,0,0); #endif diff --git a/Source/kwsys/testIOS.cxx b/Source/kwsys/testIOS.cxx index 3b971e268..f0c7f1a7b 100644 --- a/Source/kwsys/testIOS.cxx +++ b/Source/kwsys/testIOS.cxx @@ -48,7 +48,7 @@ int testIOS(int, char*[]) return 1; } static const unsigned char array[] = { 0xff,0x4f,0xff,0x51,0x00,0x29,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x01,0x01,0xff,0x52,0x00,0x0c,0x00,0x00,0x00,0x01,0x00,0x05,0x04,0x04,0x00,0x01,0xff,0x5c,0x00,0x13,0x40,0x40,0x48,0x48,0x50,0x48,0x48,0x50,0x48,0x48,0x50,0x48,0x48,0x50,0x48,0x48,0x50,0xff,0x64,0x00,0x2c,0x00,0x00,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x49,0x54,0x4b,0x2f,0x47,0x44,0x43,0x4d,0x2f,0x4f,0x70,0x65,0x6e,0x4a,0x50,0x45,0x47,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x31,0x2e,0x30,0xff,0x90,0x00,0x0a,0x00,0x00,0x00,0x00,0x06,0x2c,0x00,0x01,0xff,0x93,0xcf,0xb0,0x18,0x08,0x7f,0xc6,0x99,0xbf,0xff,0xc0,0xf8,0xc1,0xc1,0xf3,0x05,0x81,0xf2,0x83,0x0a,0xa5,0xff,0x10,0x90,0xbf,0x2f,0xff,0x04,0xa8,0x7f,0xc0,0xf8,0xc4,0xc1,0xf3,0x09,0x81,0xf3,0x0c,0x19,0x34 }; - const unsigned int narray = sizeof(array); // 180 + const size_t narray = sizeof(array); // 180 kwsys_ios::stringstream strstr; strstr.write( (char*)array, narray ); //strstr.seekp( narray / 2 ); // set position of put pointer in mid string diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx index 49a686c17..53d51ac40 100644 --- a/Source/kwsys/testSystemInformation.cxx +++ b/Source/kwsys/testSystemInformation.cxx @@ -88,14 +88,31 @@ int testSystemInformation(int, char*[]) printMethod3(info, GetHostMemoryUsed(), "KiB"); printMethod3(info, GetProcMemoryUsed(), "KiB"); - for (int i = 0; i <= 31; i++) + for (long int i = 0; i <= 31; i++) { - if (info.DoesCPUSupportFeature(1 << i)) + if (info.DoesCPUSupportFeature(static_cast<long int>(1) << i)) { kwsys_ios::cout << "CPU feature " << i << "\n"; } } - //int GetProcessorCacheXSize(long int); -// bool DoesCPUSupportFeature(long int); + + /* test stack trace + */ + kwsys_ios::cout + << "Program Stack:" << kwsys_ios::endl + << kwsys::SystemInformation::GetProgramStack(0,0) << kwsys_ios::endl + << kwsys_ios::endl; + + /* test segv handler + info.SetStackTraceOnError(1); + double *d = (double*)100; + *d=0; + */ + + /* test abort handler + info.SetStackTraceOnError(1); + abort(); + */ + return 0; } diff --git a/Tests/AliasTarget/CMakeLists.txt b/Tests/AliasTarget/CMakeLists.txt new file mode 100644 index 000000000..a5eb0f6de --- /dev/null +++ b/Tests/AliasTarget/CMakeLists.txt @@ -0,0 +1,47 @@ + +cmake_minimum_required(VERSION 2.8.11) +project(AliasTarget) + +add_library(foo SHARED empty.cpp) +add_library(PREFIX::Foo ALIAS foo) +add_library(Another::Alias ALIAS foo) + +add_library(objects OBJECT object.cpp) +add_library(Alias::Objects ALIAS objects) + +target_compile_definitions(foo PUBLIC FOO_DEFINE) + +add_library(bar SHARED empty.cpp) +target_compile_definitions(bar PUBLIC BAR_DEFINE) + +target_link_libraries(foo LINK_PUBLIC $<$<STREQUAL:$<TARGET_PROPERTY:PREFIX::Foo,ALIASED_TARGET>,foo>:bar>) + +add_executable(AliasTarget commandgenerator.cpp $<TARGET_OBJECTS:Alias::Objects>) +add_executable(PREFIX::AliasTarget ALIAS AliasTarget) +add_executable(Generator::Command ALIAS AliasTarget) + +add_custom_command(OUTPUT commandoutput.h COMMAND Generator::Command) + +add_library(bat SHARED bat.cpp "${CMAKE_CURRENT_BINARY_DIR}/commandoutput.h") +target_link_libraries(bat PREFIX::Foo) +target_include_directories(bat PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") + +add_executable(targetgenerator targetgenerator.cpp) +add_executable(Generator::Target ALIAS targetgenerator) + +add_custom_target(usealias Generator::Target) +add_dependencies(bat usealias) + +if (NOT TARGET Another::Alias) + message(SEND_ERROR "Another::Alias is not considered a target.") +endif() + +get_target_property(_alt PREFIX::Foo ALIASED_TARGET) +if (NOT ${_alt} STREQUAL foo) + message(SEND_ERROR "ALIASED_TARGET is not foo: ${_alt}") +endif() + +get_property(_alt2 TARGET PREFIX::Foo PROPERTY ALIASED_TARGET) +if (NOT ${_alt2} STREQUAL foo) + message(SEND_ERROR "ALIASED_TARGET is not foo.") +endif() diff --git a/Tests/AliasTarget/bat.cpp b/Tests/AliasTarget/bat.cpp new file mode 100644 index 000000000..1063c2175 --- /dev/null +++ b/Tests/AliasTarget/bat.cpp @@ -0,0 +1,28 @@ + +#ifndef FOO_DEFINE +#error Expected FOO_DEFINE +#endif + +#ifndef BAR_DEFINE +#error Expected Bar_DEFINE +#endif + +#include "commandoutput.h" + +#ifndef COMMANDOUTPUT_DEFINE +#error Expected COMMANDOUTPUT_DEFINE +#endif + +#include "targetoutput.h" + +#ifndef TARGETOUTPUT_DEFINE +#error Expected TARGETOUTPUT_DEFINE +#endif + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int bar() +{ + return 0; +} diff --git a/Tests/AliasTarget/commandgenerator.cpp b/Tests/AliasTarget/commandgenerator.cpp new file mode 100644 index 000000000..23560a4ba --- /dev/null +++ b/Tests/AliasTarget/commandgenerator.cpp @@ -0,0 +1,15 @@ + +#include <fstream> + +#include "object.h" + +int main(int argc, char **argv) +{ + std::fstream fout; + fout.open("commandoutput.h", std::ios::out); + if (!fout) + return 1; + fout << "#define COMMANDOUTPUT_DEFINE\n"; + fout.close(); + return object(); +} diff --git a/Tests/AliasTarget/empty.cpp b/Tests/AliasTarget/empty.cpp new file mode 100644 index 000000000..b19427ad0 --- /dev/null +++ b/Tests/AliasTarget/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int main(void) +{ + return 0; +} diff --git a/Tests/AliasTarget/object.cpp b/Tests/AliasTarget/object.cpp new file mode 100644 index 000000000..df09c20c9 --- /dev/null +++ b/Tests/AliasTarget/object.cpp @@ -0,0 +1,5 @@ + +int object(void) +{ + return 0; +} diff --git a/Tests/AliasTarget/object.h b/Tests/AliasTarget/object.h new file mode 100644 index 000000000..e935f1474 --- /dev/null +++ b/Tests/AliasTarget/object.h @@ -0,0 +1,4 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int object(void); diff --git a/Tests/AliasTarget/targetgenerator.cpp b/Tests/AliasTarget/targetgenerator.cpp new file mode 100644 index 000000000..3362414e0 --- /dev/null +++ b/Tests/AliasTarget/targetgenerator.cpp @@ -0,0 +1,13 @@ + +#include <fstream> + +int main(int argc, char **argv) +{ + std::fstream fout; + fout.open("targetoutput.h", std::ios::out); + if (!fout) + return 1; + fout << "#define TARGETOUTPUT_DEFINE\n"; + fout.close(); + return 0; +} diff --git a/Tests/Architecture/CMakeLists.txt b/Tests/Architecture/CMakeLists.txt index 927ce3fed..ea5fc0b50 100644 --- a/Tests/Architecture/CMakeLists.txt +++ b/Tests/Architecture/CMakeLists.txt @@ -7,8 +7,8 @@ function(test_for_xcode4 result_var) execute_process(COMMAND xcodebuild -version OUTPUT_VARIABLE ov RESULT_VARIABLE rv ) - if("${rv}" STREQUAL "0") - if(ov MATCHES "^Xcode 4.[0-9].*$") + if("${rv}" STREQUAL "0" AND ov MATCHES "^Xcode ([0-9]+)\\.") + if(NOT CMAKE_MATCH_1 VERSION_LESS 4) set(${result_var} 1 PARENT_SCOPE) endif() endif() diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt index 27927512a..06871543f 100644 --- a/Tests/BuildDepends/CMakeLists.txt +++ b/Tests/BuildDepends/CMakeLists.txt @@ -53,6 +53,8 @@ write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in "static const char* zot = \"zot\";\n") +file(WRITE ${BuildDepends_BINARY_DIR}/Project/dir/header.txt + "#define HEADER_STRING \"ninja\"\n" ) file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_custom.hxx.in "static const char* zot_custom = \"zot_custom\";\n") file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_macro_dir.hxx @@ -93,6 +95,26 @@ if(NOT RESULT) message(SEND_ERROR "Could not build test project (1)!") endif() +# find and save the ninjadep executable +set(ninjadep ${BuildDepends_BINARY_DIR}/Project/ninjadep${CMAKE_EXECUTABLE_SUFFIX}) +if(EXISTS + "${BuildDepends_BINARY_DIR}/Project/Debug/ninjadep${CMAKE_EXECUTABLE_SUFFIX}" ) + message("found debug") + set(ninjadep + "${BuildDepends_BINARY_DIR}/Project/Debug/ninjadep${CMAKE_EXECUTABLE_SUFFIX}") +endif() +message("Running ${ninjadep} ") +execute_process(COMMAND ${ninjadep} OUTPUT_VARIABLE out RESULT_VARIABLE runResult) +string(REGEX REPLACE "[\r\n]" " " out "${out}") +message("Run result: ${runResult} Output: \"${out}\"") + +if("${out}" STREQUAL "HEADER_STRING: ninja ") + message("Worked!") +else() + message(SEND_ERROR "Project did not rebuild properly. Output[${out}]\n" + " expected [HEADER_STRING: ninja]") +endif() + set(bar ${BuildDepends_BINARY_DIR}/Project/bar${CMAKE_EXECUTABLE_SUFFIX}) if(EXISTS "${BuildDepends_BINARY_DIR}/Project/Debug/bar${CMAKE_EXECUTABLE_SUFFIX}" ) @@ -151,6 +173,8 @@ execute_process(COMMAND ${bar} -infinite TIMEOUT 3 OUTPUT_VARIABLE out) message("Modifying Project/foo.cxx") write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx "const char* foo() { return \"foo changed\";}" ) +file(WRITE "${BuildDepends_BINARY_DIR}/Project/dir/header.txt" + "#define HEADER_STRING \"ninja changed\"\n" ) file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in "static const char* zot = \"zot changed\";\n") file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_custom.hxx.in @@ -204,6 +228,21 @@ if(EXISTS message("found debug") endif() +message("Running ${ninjadep} ") +execute_process(COMMAND ${ninjadep} OUTPUT_VARIABLE out RESULT_VARIABLE runResult) +string(REGEX REPLACE "[\r\n]" " " out "${out}") +message("Run result: ${runResult} Output: \"${out}\"") + +if("${out}" STREQUAL "HEADER_STRING: ninja changed ") + message("Worked!") +elseif(CMAKE_GENERATOR STREQUAL "Visual Studio 6") + # Tolerate failure because VS 6 does not seem to recompile ninjadep.cpp + # when the "dir/header.h" it includes changes. +else() + message(SEND_ERROR "Project did not rebuild properly. Output[${out}]\n" + " expected [HEADER_STRING: ninja changed]") +endif() + message("Running ${bar} ") execute_process(COMMAND ${bar} OUTPUT_VARIABLE out RESULT_VARIABLE runResult) string(REGEX REPLACE "[\r\n]" " " out "${out}") @@ -246,6 +285,8 @@ if(EXISTS "${link_depends_no_shared_check_txt}") file(STRINGS "${link_depends_no_shared_check_txt}" link_depends_no_shared_check LIMIT_COUNT 1) if("${link_depends_no_shared_check}" STREQUAL "0") message(STATUS "link_depends_no_shared_exe is older than link_depends_no_shared_lib as expected.") + elseif(XCODE AND NOT XCODE_VERSION VERSION_LESS 5) + message(STATUS "Known limitation: link_depends_no_shared_exe is newer than link_depends_no_shared_lib but we cannot stop Xcode ${XCODE_VERSION} from enforcing this dependency.") else() message(SEND_ERROR "Project did not rebuild properly: link_depends_no_shared_exe is newer than link_depends_no_shared_lib.") endif() diff --git a/Tests/BuildDepends/Project/CMakeLists.txt b/Tests/BuildDepends/Project/CMakeLists.txt index f8a3d1550..8806ecdf1 100644 --- a/Tests/BuildDepends/Project/CMakeLists.txt +++ b/Tests/BuildDepends/Project/CMakeLists.txt @@ -7,8 +7,8 @@ function(test_for_xcode4 result_var) execute_process(COMMAND xcodebuild -version OUTPUT_VARIABLE ov RESULT_VARIABLE rv ) - if("${rv}" STREQUAL "0") - if(ov MATCHES "^Xcode 4.[0-9].*$") + if("${rv}" STREQUAL "0" AND ov MATCHES "^Xcode ([0-9]+)\\.") + if(NOT CMAKE_MATCH_1 VERSION_LESS 4) set(${result_var} 1 PARENT_SCOPE) endif() endif() @@ -123,3 +123,19 @@ add_custom_target(link_depends_no_shared_check ALL -P ${CMAKE_CURRENT_SOURCE_DIR}/link_depends_no_shared_check.cmake ) add_dependencies(link_depends_no_shared_check link_depends_no_shared_exe) + +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dir/header.h + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dir/header.txt + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/dir/header.txt + ${CMAKE_CURRENT_BINARY_DIR}/dir/header.h + ) + +set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/dir/header.h + PROPERTIES GENERATED 1) + +add_custom_target(header_tgt DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dir/header.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +add_executable(ninjadep ninjadep.cpp) +add_dependencies(ninjadep header_tgt) diff --git a/Tests/BuildDepends/Project/ninjadep.cpp b/Tests/BuildDepends/Project/ninjadep.cpp new file mode 100644 index 000000000..8d6133613 --- /dev/null +++ b/Tests/BuildDepends/Project/ninjadep.cpp @@ -0,0 +1,6 @@ +#include <stdio.h> +#include "dir/header.h" + +int main() { + printf("HEADER_STRING: %s\n", HEADER_STRING); +} diff --git a/Tests/BundleUtilities/CMakeLists.txt b/Tests/BundleUtilities/CMakeLists.txt index 8f24afe9a..5cc7071b4 100644 --- a/Tests/BundleUtilities/CMakeLists.txt +++ b/Tests/BundleUtilities/CMakeLists.txt @@ -12,8 +12,7 @@ add_library(shared2 SHARED shared2.cpp shared2.h) # a framework library add_library(framework SHARED framework.cpp framework.h) -# TODO: fix problems with local frameworks without rpaths -#set_target_properties(framework PROPERTIES FRAMEWORK 1) +set_target_properties(framework PROPERTIES FRAMEWORK 1) # make sure rpaths are not helping BundleUtilities or the executables set_target_properties(shared shared2 framework PROPERTIES diff --git a/Tests/CFBundleTest/CMakeLists.txt b/Tests/CFBundleTest/CMakeLists.txt index 8fd9efdc6..bf9771c8b 100644 --- a/Tests/CFBundleTest/CMakeLists.txt +++ b/Tests/CFBundleTest/CMakeLists.txt @@ -54,3 +54,5 @@ set_source_files_properties( ${CMAKE_CURRENT_BINARY_DIR}/InfoPlist.strings ${CMAKE_CURRENT_BINARY_DIR}/Localized.rsrc PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/English.lproj") + +export(TARGETS CFBundleTest FILE ${CMAKE_CURRENT_BINARY_DIR}/exp.cmake) diff --git a/Tests/CMakeCommands/add_compile_options/CMakeLists.txt b/Tests/CMakeCommands/add_compile_options/CMakeLists.txt new file mode 100644 index 000000000..1652cf665 --- /dev/null +++ b/Tests/CMakeCommands/add_compile_options/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.8) + +project(add_compile_options) + +add_compile_options(-DTEST_OPTION) + +add_executable(add_compile_options main.cpp) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(add_compile_options + PRIVATE + "DO_GNU_TESTS" + ) +endif() diff --git a/Tests/CMakeCommands/add_compile_options/main.cpp b/Tests/CMakeCommands/add_compile_options/main.cpp new file mode 100644 index 000000000..2bb20ac75 --- /dev/null +++ b/Tests/CMakeCommands/add_compile_options/main.cpp @@ -0,0 +1,11 @@ + +#ifdef DO_GNU_TESTS +# ifndef TEST_OPTION +# error Expected TEST_OPTION +# endif +#endif + +int main(void) +{ + return 0; +} diff --git a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt index 6d0e64615..900dbd028 100644 --- a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt +++ b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt @@ -20,3 +20,8 @@ target_compile_definitions(consumer PRIVATE $<TARGET_PROPERTY:target_compile_definitions,INTERFACE_COMPILE_DEFINITIONS> -DDASH_D_DEFINE ) + +# Test no items +target_compile_definitions(consumer + PRIVATE +) diff --git a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt new file mode 100644 index 000000000..1d0463927 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt @@ -0,0 +1,40 @@ + +cmake_minimum_required(VERSION 2.8) + +project(target_compile_options) + +add_executable(target_compile_options + "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" +) +target_compile_options(target_compile_options + PRIVATE $<$<CXX_COMPILER_ID:GNU>:-DMY_PRIVATE_DEFINE> + PUBLIC $<$<CXX_COMPILER_ID:GNU>:-DMY_PUBLIC_DEFINE> + INTERFACE $<$<CXX_COMPILER_ID:GNU>:-DMY_INTERFACE_DEFINE> +) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(target_compile_options + PRIVATE + "DO_GNU_TESTS" + ) +endif() + +add_executable(consumer + "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp" +) + +target_compile_options(consumer + PRIVATE $<$<CXX_COMPILER_ID:GNU>:$<TARGET_PROPERTY:target_compile_options,INTERFACE_COMPILE_OPTIONS>> +) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(consumer + PRIVATE + "DO_GNU_TESTS" + ) +endif() + +# Test no items +target_compile_options(consumer + PRIVATE +) diff --git a/Tests/CMakeCommands/target_compile_options/consumer.cpp b/Tests/CMakeCommands/target_compile_options/consumer.cpp new file mode 100644 index 000000000..12996065b --- /dev/null +++ b/Tests/CMakeCommands/target_compile_options/consumer.cpp @@ -0,0 +1,18 @@ + +#ifdef DO_GNU_TESTS + +# ifdef MY_PRIVATE_DEFINE +# error Unexpected MY_PRIVATE_DEFINE +# endif + +# ifndef MY_PUBLIC_DEFINE +# error Expected MY_PUBLIC_DEFINE +# endif + +# ifndef MY_INTERFACE_DEFINE +# error Expected MY_INTERFACE_DEFINE +# endif + +#endif + +int main() { return 0; } diff --git a/Tests/CMakeCommands/target_compile_options/main.cpp b/Tests/CMakeCommands/target_compile_options/main.cpp new file mode 100644 index 000000000..961c06dd7 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_options/main.cpp @@ -0,0 +1,18 @@ + +#ifdef DO_GNU_TESTS + +# ifndef MY_PRIVATE_DEFINE +# error Expected MY_PRIVATE_DEFINE +# endif + +# ifndef MY_PUBLIC_DEFINE +# error Expected MY_PUBLIC_DEFINE +# endif + +# ifdef MY_INTERFACE_DEFINE +# error Unexpected MY_INTERFACE_DEFINE +# endif + +#endif + +int main() { return 0; } diff --git a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt index c03f0f84b..21b8e1530 100644 --- a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt +++ b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt @@ -47,3 +47,17 @@ target_include_directories(consumer $<TARGET_PROPERTY:target_include_directories,INTERFACE_INCLUDE_DIRECTORIES> relative_dir ) + +# Test no items +target_include_directories(consumer + PRIVATE +) +target_include_directories(consumer + BEFORE PRIVATE +) +target_include_directories(consumer + SYSTEM BEFORE PRIVATE +) +target_include_directories(consumer + SYSTEM PRIVATE +) diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index 388164455..06019e691 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -114,3 +114,19 @@ endif() # shortcutting of the evaluation by returning an empty string. set(_exe_test $<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>) target_link_libraries(targetC $<$<AND:${_exe_test},${_exe_test}>:depG>) + +add_library(libConsumer empty.cpp) +# This line causes $<$<CONFIG:Debug>:depA> to be used when +# determining the include directories for libConsumer based on the +# interface properties of its LINK_LIBRARIES. Because the above expression +# evaluates to the empty string in non-Debug cases, ensure that that causes +# no problems. +target_link_libraries(libConsumer debug depA) + +add_subdirectory(cmp0022) + +add_executable(newsignature1 newsignature1.cpp) +target_link_libraries(newsignature1 PRIVATE depC INTERFACE depD PUBLIC depB PRIVATE subdirlib INTERFACE INTERFACE PUBLIC) + +assert_property(newsignature1 INTERFACE_LINK_LIBRARIES "depD;depB") +assert_property(newsignature1 LINK_LIBRARIES "depC;depB;subdirlib") diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt new file mode 100644 index 000000000..818b8c99c --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt @@ -0,0 +1,37 @@ + +include(GenerateExportHeader) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +cmake_policy(SET CMP0022 NEW) +add_library(cmp0022lib SHARED cmp0022lib.cpp) +generate_export_header(cmp0022lib) +add_library(cmp0022ifacelib SHARED cmp0022ifacelib.cpp) +generate_export_header(cmp0022ifacelib) +target_link_libraries(cmp0022lib LINK_PUBLIC cmp0022ifacelib) + +assert_property(cmp0022lib LINK_INTERFACE_LIBRARIES "") +assert_property(cmp0022ifacelib LINK_INTERFACE_LIBRARIES "") +assert_property(cmp0022lib INTERFACE_LINK_LIBRARIES "cmp0022ifacelib") +assert_property(cmp0022ifacelib INTERFACE_LINK_LIBRARIES "") + +add_executable(cmp0022exe cmp0022exe.cpp) +target_link_libraries(cmp0022exe cmp0022lib) + +add_library(staticlib1 STATIC staticlib1.cpp) +generate_export_header(staticlib1) +add_library(staticlib2 STATIC staticlib2.cpp) +generate_export_header(staticlib2) +target_link_libraries(staticlib1 LINK_PUBLIC staticlib2) +if (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang) + target_link_libraries(staticlib1 LINK_PRIVATE "-Wl,-v") +endif() + +add_executable(staticlib_exe staticlib_exe.cpp) +target_link_libraries(staticlib_exe staticlib1) + +add_library(onlyplainlib1 SHARED onlyplainlib1.cpp) +add_library(onlyplainlib2 SHARED onlyplainlib2.cpp) +target_link_libraries(onlyplainlib2 onlyplainlib1) + +add_executable(onlyplainlib_user onlyplainlib_user.cpp) +target_link_libraries(onlyplainlib_user onlyplainlib2) diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022exe.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022exe.cpp new file mode 100644 index 000000000..008bb74b5 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022exe.cpp @@ -0,0 +1,7 @@ + +#include "cmp0022lib.h" + +int main(void) +{ + return cmp0022().Value; +} diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022ifacelib.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022ifacelib.cpp new file mode 100644 index 000000000..b285be022 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022ifacelib.cpp @@ -0,0 +1,9 @@ + +#include "cmp0022ifacelib.h" + +CMP0022Iface cmp0022iface() +{ + CMP0022Iface iface; + iface.Value = 0; + return iface; +} diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022ifacelib.h b/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022ifacelib.h new file mode 100644 index 000000000..616dbf644 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022ifacelib.h @@ -0,0 +1,9 @@ + +#include "cmp0022ifacelib_export.h" + +struct CMP0022Iface +{ + int Value; +}; + +CMP0022Iface CMP0022IFACELIB_EXPORT cmp0022iface(); diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022lib.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022lib.cpp new file mode 100644 index 000000000..381d463ff --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022lib.cpp @@ -0,0 +1,7 @@ + +#include "cmp0022lib.h" + +CMP0022Iface cmp0022() +{ + return cmp0022iface(); +} diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022lib.h b/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022lib.h new file mode 100644 index 000000000..3235b9bf1 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/cmp0022lib.h @@ -0,0 +1,6 @@ + +#include "cmp0022lib_export.h" + +#include "cmp0022ifacelib.h" + +CMP0022Iface CMP0022LIB_EXPORT cmp0022(); diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib1.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib1.cpp new file mode 100644 index 000000000..41dc3ce18 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib1.cpp @@ -0,0 +1,13 @@ + +#include "onlyplainlib1.h" + +OnlyPlainLib1::OnlyPlainLib1() + : result(0) +{ + +} + +int OnlyPlainLib1::GetResult() +{ + return result; +} diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib1.h b/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib1.h new file mode 100644 index 000000000..c0373ceb3 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib1.h @@ -0,0 +1,14 @@ + +struct +#ifdef _WIN32 +__declspec(dllexport) +#endif +OnlyPlainLib1 +{ + OnlyPlainLib1(); + + int GetResult(); + +private: + int result; +}; diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib2.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib2.cpp new file mode 100644 index 000000000..2865ae91a --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib2.cpp @@ -0,0 +1,8 @@ + +#include "onlyplainlib2.h" + +OnlyPlainLib1 onlyPlainLib2() +{ + OnlyPlainLib1 opl1; + return opl1; +} diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib2.h b/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib2.h new file mode 100644 index 000000000..74b18a00e --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib2.h @@ -0,0 +1,7 @@ + +#include "onlyplainlib1.h" + +#ifdef _WIN32 +__declspec(dllexport) +#endif +OnlyPlainLib1 onlyPlainLib2(); diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib_user.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib_user.cpp new file mode 100644 index 000000000..0fb7b0a67 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/onlyplainlib_user.cpp @@ -0,0 +1,7 @@ + +#include "onlyplainlib2.h" + +int main(int argc, char **argv) +{ + return onlyPlainLib2().GetResult(); +} diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp new file mode 100644 index 000000000..a253c46f6 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp @@ -0,0 +1,2 @@ + +int staticlib1() { return 0; } diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.h b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.h new file mode 100644 index 000000000..4bbf23ffd --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.h @@ -0,0 +1,4 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int staticlib1(); diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp new file mode 100644 index 000000000..4e38063b5 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp @@ -0,0 +1,2 @@ + +int staticlib2() { return 0; } diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.h b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.h new file mode 100644 index 000000000..a4e07b6c1 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.h @@ -0,0 +1,4 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int staticlib2(); diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib_exe.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib_exe.cpp new file mode 100644 index 000000000..97adc40db --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib_exe.cpp @@ -0,0 +1,8 @@ + +#include "staticlib1.h" +#include "staticlib2.h" + +int main() +{ + return staticlib1() + staticlib2(); +} diff --git a/Tests/CMakeCommands/target_link_libraries/newsignature1.cpp b/Tests/CMakeCommands/target_link_libraries/newsignature1.cpp new file mode 100644 index 000000000..d1321a15f --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/newsignature1.cpp @@ -0,0 +1,19 @@ + +#include "depB.h" +#include "depC.h" +#include "depIfaceOnly.h" + +#include "subdirlib.h" + +int main(int, char **) +{ + DepA a; + DepB b; + DepC c; + + DepIfaceOnly iface_only; + + SubDirLibObject sd; + + return a.foo() + b.foo() + c.foo() + iface_only.foo() + sd.foo(); +} diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index 4e819f470..a831e3015 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -12,6 +12,14 @@ set(CMakeLib_TESTS testXMLSafe ) +if(WIN32 AND NOT UNIX) # Just if(WIN32) when CMake >= 2.8.4 is required + list(APPEND CMakeLib_TESTS + testVisualStudioSlnParser + ) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testVisualStudioSlnParser.h.in + ${CMAKE_CURRENT_BINARY_DIR}/testVisualStudioSlnParser.h @ONLY) +endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testXMLParser.h.in ${CMAKE_CURRENT_BINARY_DIR}/testXMLParser.h @ONLY) diff --git a/Tests/CMakeLib/testVisualStudioSlnParser.cxx b/Tests/CMakeLib/testVisualStudioSlnParser.cxx new file mode 100644 index 000000000..5b62f239f --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser.cxx @@ -0,0 +1,185 @@ +#include "testVisualStudioSlnParser.h" + +#include "cmVisualStudioSlnData.h" +#include "cmVisualStudioSlnParser.h" + +#include <cmsys/ios/iostream> + +//---------------------------------------------------------------------------- +static bool parsedRight(cmVisualStudioSlnParser& parser, + const std::string& file, cmSlnData& data, + cmVisualStudioSlnParser::ParseResult expected = + cmVisualStudioSlnParser::ResultOK) +{ + if (parser.ParseFile(SOURCE_DIR "/testVisualStudioSlnParser_data/" + file + + "." SLN_EXTENSION, + data, cmVisualStudioSlnParser::DataGroupProjects)) + { + if (expected == cmVisualStudioSlnParser::ResultOK) + { + return true; + } + } + else + { + if (parser.GetParseResult() == expected) + { + return true; + } + } + cmsys_ios::cerr << "cmVisualStudioSlnParser mis-parsed " << file + << "." SLN_EXTENSION << "; expected result " << expected + << ", got " << parser.GetParseResult() + << cmsys_ios::endl; + return false; +} + +//---------------------------------------------------------------------------- +int testVisualStudioSlnParser(int, char*[]) +{ + cmVisualStudioSlnParser parser; + + // Test clean parser + if (parser.GetParseResult() != cmVisualStudioSlnParser::ResultOK) + { + cmsys_ios::cerr << "cmVisualStudioSlnParser initialisation failed" + << cmsys_ios::endl; + return 1; + } + + // Test parsing valid sln + { + cmSlnData data; + if (!parsedRight(parser, "valid", data)) + { + return 1; + } + const std::vector<cmSlnProjectEntry>& projects = data.GetProjects(); + const char * const names[] = + { + "3rdParty", "ALL_BUILD", "CMakeLib", "CMakeLibTests", + "CMakePredefinedTargets", "CPackLib", "CTestDashboardTargets", "CTestLib", + "Continuous", "Documentation", + "Experimental", "INSTALL", "KWSys", "LIBCURL", "Nightly", + "NightlyMemoryCheck", "PACKAGE", "RUN_TESTS", "Tests", "Utilities", + "Win9xCompat", "ZERO_CHECK", "cmIML_test", "cmake", "cmbzip2", "cmcldeps", + "cmcompress", "cmcurl", "cmexpat", "cmlibarchive", "cmsys", + "cmsysEncodeExecutable", "cmsysProcessFwd9x", "cmsysTestDynload", + "cmsysTestProcess", "cmsysTestSharedForward", "cmsysTestsC", + "cmsysTestsCxx", "cmsys_c", "cmw9xcom", "cmzlib", "cpack", "ctest", + "documentation", "memcheck_fail", "pseudo_BC", "pseudo_purify", + "pseudo_valgrind", "test_clean", "uninstall" + }; + const size_t expectedProjectCount = sizeof(names) / sizeof(*names); + if (projects.size() != expectedProjectCount) + { + cmsys_ios::cerr << "cmVisualStudioSlnParser returned bad number of " + << "projects (" << projects.size() << " instead of " + << expectedProjectCount << ')' + << cmsys_ios::endl; + return 1; + } + for (size_t idx = 0; idx < expectedProjectCount; ++idx) + { + if (projects[idx].GetName() != names[idx]) + { + cmsys_ios::cerr << "cmVisualStudioSlnParser returned bad project #" + << idx << "; expected \"" << names[idx] << "\", got \"" + << projects[idx].GetName() << '"' + << cmsys_ios::endl; + return 1; + } + } + if (projects[0].GetRelativePath() != "Utilities\\3rdParty") + { + cmsys_ios::cerr << "cmVisualStudioSlnParser returned bad relative path of " + << "project 3rdParty; expected \"Utilities\\3rdParty\", " + << "got \"" << projects[0].GetRelativePath() << '"' + << cmsys_ios::endl; + return 1; + } + if (projects[2].GetGUID() != "{59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}") + { + cmsys_ios::cerr << "cmVisualStudioSlnParser returned bad relative path of " + << "project CMakeLib; expected " + << "\"{59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}\", " + << "got \"" << projects[2].GetGUID() << '"' + << cmsys_ios::endl; + return 1; + } + } + + // Test BOM parsing + { + cmSlnData data; + + if (!parsedRight(parser, "bom", data)) + { + return 1; + } + if (!parser.GetParseHadBOM()) + { + cmsys_ios::cerr << "cmVisualStudioSlnParser didn't find BOM in bom." + << SLN_EXTENSION + << cmsys_ios::endl; + return 1; + } + + if (!parsedRight(parser, "nobom", data)) + { + return 1; + } + if (parser.GetParseHadBOM()) + { + cmsys_ios::cerr << "cmVisualStudioSlnParser found BOM in nobom." + << SLN_EXTENSION + << cmsys_ios::endl; + return 1; + } + } + + // Test invalid sln + { + { + cmSlnData data; + if (!parsedRight(parser, "err-nonexistent", data, + cmVisualStudioSlnParser::ResultErrorOpeningInput)) + { + return 1; + } + } + { + cmSlnData data; + if (!parsedRight(parser, "err-empty", data, + cmVisualStudioSlnParser::ResultErrorReadingInput)) + { + return 1; + } + } + const char * const files[] = + { + "header", "projectArgs", "topLevel", "projectContents", "projectSection", + "global", "unclosed", "strayQuote", "strayParen", "strayQuote2" + }; + for (size_t idx = 0; idx < sizeof(files) / sizeof(files[0]); ++idx) + { + cmSlnData data; + if (!parsedRight(parser, std::string("err-structure-") + files[idx], data, + cmVisualStudioSlnParser::ResultErrorInputStructure)) + { + return 1; + } + } + { + cmSlnData data; + if (!parsedRight(parser, "err-data", data, + cmVisualStudioSlnParser::ResultErrorInputData)) + { + return 1; + } + } + } + + // All is well + return 0; +} diff --git a/Tests/CMakeLib/testVisualStudioSlnParser.h.in b/Tests/CMakeLib/testVisualStudioSlnParser.h.in new file mode 100644 index 000000000..62c3f4dcc --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser.h.in @@ -0,0 +1,7 @@ +#ifndef testVisualStudioSlnParser_h +#define testVisualStudioSlnParser_h + +#define SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@" +#define SLN_EXTENSION "sln-file" + +#endif diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/.gitattributes b/Tests/CMakeLib/testVisualStudioSlnParser_data/.gitattributes new file mode 100644 index 000000000..5be3dc5bc --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/.gitattributes @@ -0,0 +1 @@ +*.sln-file -crlf whitespace=cr-at-eol diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/bom.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/bom.sln-file new file mode 100644 index 000000000..52c2483f4 --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/bom.sln-file @@ -0,0 +1,2 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-data.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-data.sln-file new file mode 100644 index 000000000..bd66ed41d --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-data.sln-file @@ -0,0 +1,6 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Continuous", "Continuous.vcxproj", "{E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Continuous", "Continuous.vcxproj", "{E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}"
+EndProject
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-empty.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-empty.sln-file new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-empty.sln-file diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-global.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-global.sln-file new file mode 100644 index 000000000..32176b882 --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-global.sln-file @@ -0,0 +1,9 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Continuous", "Continuous.vcxproj", "{E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Global
+EndGlobalSection
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-header.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-header.sln-file new file mode 100644 index 000000000..f838a7112 --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-header.sln-file @@ -0,0 +1,4 @@ +Microsoft Visual Studio Solution2 File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Continuous", "Continuous.vcxproj", "{E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}"
+EndProject
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-projectArgs.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-projectArgs.sln-file new file mode 100644 index 000000000..3e8d35a4f --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-projectArgs.sln-file @@ -0,0 +1,4 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Continuous", "Continuous.vcxproj"
+EndProject
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-projectContents.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-projectContents.sln-file new file mode 100644 index 000000000..e0d58c92b --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-projectContents.sln-file @@ -0,0 +1,6 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Continuous", "Continuous.vcxproj", "{E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}"
+ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Continuous2", "Continuous2.vcxproj", "{E5071091-DBFB-49E2-AF0F-E8B0FDEF6C89}"
+ EndProject
+EndProject
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-projectSection.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-projectSection.sln-file new file mode 100644 index 000000000..ed0aa0259 --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-projectSection.sln-file @@ -0,0 +1,11 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "ZERO_CHECK.vcxproj", "{90BC31D7-A3E8-4F04-8049-2236C239A044}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Continuous", "Continuous.vcxproj", "{E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProject
+EndProject
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-strayParen.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-strayParen.sln-file new file mode 100644 index 000000000..d2bb9e3e5 --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-strayParen.sln-file @@ -0,0 +1,4 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}" = "Continuous", "Continuous.vcxproj", "{E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}"
+EndProject
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-strayQuote.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-strayQuote.sln-file new file mode 100644 index 000000000..3c1a2ecca --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-strayQuote.sln-file @@ -0,0 +1,4 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Continuous", "Continuous.vcxproj", "{E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}
+EndProject
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-strayQuote2.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-strayQuote2.sln-file new file mode 100644 index 000000000..db8bbcf2c --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-strayQuote2.sln-file @@ -0,0 +1,4 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}) = "Continuous", "Continuous.vcxproj", "{E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}"
+EndProject
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-topLevel.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-topLevel.sln-file new file mode 100644 index 000000000..1727bf378 --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-topLevel.sln-file @@ -0,0 +1,4 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+GlobalSection(ExtensibilityGlobals) = postSolution
+EndGlobalSection
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-unclosed.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-unclosed.sln-file new file mode 100644 index 000000000..4e6909ef5 --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/err-structure-unclosed.sln-file @@ -0,0 +1,5 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Global
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/nobom.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/nobom.sln-file new file mode 100644 index 000000000..fc1e4e947 --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/nobom.sln-file @@ -0,0 +1,2 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
diff --git a/Tests/CMakeLib/testVisualStudioSlnParser_data/valid.sln-file b/Tests/CMakeLib/testVisualStudioSlnParser_data/valid.sln-file new file mode 100644 index 000000000..7ba28a2f6 --- /dev/null +++ b/Tests/CMakeLib/testVisualStudioSlnParser_data/valid.sln-file @@ -0,0 +1,680 @@ +Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2} = {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}
+ {B025BD09-8389-4D9F-9150-F33418A664B1} = {B025BD09-8389-4D9F-9150-F33418A664B1}
+ {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8} = {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}
+ {1002C8FC-7242-4A69-AF51-C59BB10BA6D8} = {1002C8FC-7242-4A69-AF51-C59BB10BA6D8}
+ {0283B293-0067-4D02-ADA6-892704398F48} = {0283B293-0067-4D02-ADA6-892704398F48}
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {48D43A03-3C1B-439A-9517-8F2A2B4CEC3B} = {48D43A03-3C1B-439A-9517-8F2A2B4CEC3B}
+ {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8} = {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0} = {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}
+ {A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84} = {A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84}
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C} = {561AD1BB-6DD3-466D-B270-3696DEE8C26C}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3} = {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54} = {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {BDB424DC-15B3-4A06-A1E2-3D61380F359F}
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE} = {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996} = {29D5FCAF-20D0-4DEF-8529-F035C249E996}
+ {A0421DCA-AC3E-42D0-94AC-379A21A1E591} = {A0421DCA-AC3E-42D0-94AC-379A21A1E591}
+ {C6AF7E57-CE57-4462-AE1D-BF520701480E} = {C6AF7E57-CE57-4462-AE1D-BF520701480E}
+ {F2CAAAB3-9568-4284-B8E3-13955183A6D7} = {F2CAAAB3-9568-4284-B8E3-13955183A6D7}
+ {D8294E4A-03C5-43D7-AE35-15603F502DC0} = {D8294E4A-03C5-43D7-AE35-15603F502DC0}
+ {A4921D15-411F-436A-B6F3-F8381652A8E1} = {A4921D15-411F-436A-B6F3-F8381652A8E1}
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C} = {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}
+ {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C} = {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ {0E9E295F-3854-415B-AE9F-7B62F17932F5} = {0E9E295F-3854-415B-AE9F-7B62F17932F5}
+ {4BFA4D7C-C6F7-4270-9E87-B922DCE05644} = {4BFA4D7C-C6F7-4270-9E87-B922DCE05644}
+ {F77AD922-B4BC-43D7-B268-865312085495} = {F77AD922-B4BC-43D7-B268-865312085495}
+ {8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88} = {8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88}
+ {1DFA0599-77CC-4768-B47A-107EEE86C20C} = {1DFA0599-77CC-4768-B47A-107EEE86C20C}
+ {0E45A3EF-8636-46CF-94A3-7B5CE875DE48} = {0E45A3EF-8636-46CF-94A3-7B5CE875DE48}
+ {CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C} = {CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CMakeLib", "Source\CMakeLib.vcxproj", "{59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0} = {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C} = {561AD1BB-6DD3-466D-B270-3696DEE8C26C}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3} = {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54} = {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {BDB424DC-15B3-4A06-A1E2-3D61380F359F}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CMakeLibTests", "Tests\CMakeLib\CMakeLibTests.vcxproj", "{B025BD09-8389-4D9F-9150-F33418A664B1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2} = {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0} = {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C} = {561AD1BB-6DD3-466D-B270-3696DEE8C26C}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3} = {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54} = {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {BDB424DC-15B3-4A06-A1E2-3D61380F359F}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPackLib", "Source\CPackLib.vcxproj", "{94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2} = {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0} = {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C} = {561AD1BB-6DD3-466D-B270-3696DEE8C26C}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3} = {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54} = {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {BDB424DC-15B3-4A06-A1E2-3D61380F359F}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CTestLib", "Source\CTestLib.vcxproj", "{1002C8FC-7242-4A69-AF51-C59BB10BA6D8}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2} = {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0} = {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C} = {561AD1BB-6DD3-466D-B270-3696DEE8C26C}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3} = {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54} = {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {BDB424DC-15B3-4A06-A1E2-3D61380F359F}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Continuous", "Continuous.vcxproj", "{E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Experimental", "Experimental.vcxproj", "{B28E8445-DFD2-46EA-BA6C-C2A1864F2FB1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "INSTALL", "INSTALL.vcxproj", "{3B126B2D-DEAA-4CDF-9F44-28D3600F5754}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C} = {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LIBCURL", "Utilities\cmcurl\LIBCURL.vcxproj", "{0283B293-0067-4D02-ADA6-892704398F48}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Nightly", "Nightly.vcxproj", "{7BAF09E0-DCD4-4567-9486-79E1E5F18333}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NightlyMemoryCheck", "NightlyMemoryCheck.vcxproj", "{D0413FDA-31C5-41C2-A53A-C1B87061EC96}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PACKAGE", "PACKAGE.vcxproj", "{4C488FF0-7C06-47FE-A8FD-67DAD51A3E85}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C} = {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RUN_TESTS", "RUN_TESTS.vcxproj", "{D87B08A8-638E-43FA-96C2-404B41363D3B}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "ZERO_CHECK.vcxproj", "{90BC31D7-A3E8-4F04-8049-2236C239A044}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmIML_test", "Utilities\KWIML\test\cmIML_test.vcxproj", "{48D43A03-3C1B-439A-9517-8F2A2B4CEC3B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmake", "Source\cmake.vcxproj", "{6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2} = {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0} = {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C} = {561AD1BB-6DD3-466D-B270-3696DEE8C26C}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3} = {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54} = {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {BDB424DC-15B3-4A06-A1E2-3D61380F359F}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmbzip2", "Utilities\cmbzip2\cmbzip2.vcxproj", "{1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmcldeps", "Source\cmcldeps.vcxproj", "{A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2} = {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0} = {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C} = {561AD1BB-6DD3-466D-B270-3696DEE8C26C}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3} = {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54} = {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {BDB424DC-15B3-4A06-A1E2-3D61380F359F}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmcompress", "Utilities\cmcompress\cmcompress.vcxproj", "{561AD1BB-6DD3-466D-B270-3696DEE8C26C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmcurl", "Utilities\cmcurl\cmcurl.vcxproj", "{1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmexpat", "Utilities\cmexpat\cmexpat.vcxproj", "{459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmlibarchive", "Utilities\cmlibarchive\libarchive\cmlibarchive.vcxproj", "{25A91A7A-9C4E-420C-98BD-2D1F0165DA54}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0} = {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmsys", "Source\kwsys\cmsys.vcxproj", "{BDB424DC-15B3-4A06-A1E2-3D61380F359F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE} = {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996} = {29D5FCAF-20D0-4DEF-8529-F035C249E996}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmsysEncodeExecutable", "Source\kwsys\cmsysEncodeExecutable.vcxproj", "{4810B052-899E-4CA5-A0BC-2E383F8AEFAE}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmsysProcessFwd9x", "Source\kwsys\cmsysProcessFwd9x.vcxproj", "{29D5FCAF-20D0-4DEF-8529-F035C249E996}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmsysTestDynload", "Source\kwsys\cmsysTestDynload.vcxproj", "{A0421DCA-AC3E-42D0-94AC-379A21A1E591}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {BDB424DC-15B3-4A06-A1E2-3D61380F359F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmsysTestProcess", "Source\kwsys\cmsysTestProcess.vcxproj", "{C6AF7E57-CE57-4462-AE1D-BF520701480E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C} = {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmsysTestSharedForward", "Source\kwsys\cmsysTestSharedForward.vcxproj", "{F2CAAAB3-9568-4284-B8E3-13955183A6D7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C} = {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmsysTestsC", "Source\kwsys\cmsysTestsC.vcxproj", "{D8294E4A-03C5-43D7-AE35-15603F502DC0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C} = {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmsysTestsCxx", "Source\kwsys\cmsysTestsCxx.vcxproj", "{A4921D15-411F-436A-B6F3-F8381652A8E1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {BDB424DC-15B3-4A06-A1E2-3D61380F359F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmsys_c", "Source\kwsys\cmsys_c.vcxproj", "{60BEB3AF-B4EF-4363-8747-C40177BC2D9C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE} = {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996} = {29D5FCAF-20D0-4DEF-8529-F035C249E996}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmw9xcom", "Source\cmw9xcom.vcxproj", "{ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2} = {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0} = {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C} = {561AD1BB-6DD3-466D-B270-3696DEE8C26C}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3} = {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54} = {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {BDB424DC-15B3-4A06-A1E2-3D61380F359F}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmzlib", "Utilities\cmzlib\cmzlib.vcxproj", "{0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpack", "Source\cpack.vcxproj", "{0E9E295F-3854-415B-AE9F-7B62F17932F5}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2} = {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}
+ {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8} = {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ctest", "Source\ctest.vcxproj", "{4BFA4D7C-C6F7-4270-9E87-B922DCE05644}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2} = {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}
+ {1002C8FC-7242-4A69-AF51-C59BB10BA6D8} = {1002C8FC-7242-4A69-AF51-C59BB10BA6D8}
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "documentation", "Utilities\documentation.vcxproj", "{F77AD922-B4BC-43D7-B268-865312085495}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8} = {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}
+ {0E9E295F-3854-415B-AE9F-7B62F17932F5} = {0E9E295F-3854-415B-AE9F-7B62F17932F5}
+ {4BFA4D7C-C6F7-4270-9E87-B922DCE05644} = {4BFA4D7C-C6F7-4270-9E87-B922DCE05644}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memcheck_fail", "Tests\CTestTestMemcheck\memcheck_fail.vcxproj", "{8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pseudo_BC", "Tests\CTestTestMemcheck\pseudo_BC.vcxproj", "{1DFA0599-77CC-4768-B47A-107EEE86C20C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pseudo_purify", "Tests\CTestTestMemcheck\pseudo_purify.vcxproj", "{0E45A3EF-8636-46CF-94A3-7B5CE875DE48}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pseudo_valgrind", "Tests\CTestTestMemcheck\pseudo_valgrind.vcxproj", "{CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_clean", "Tests\test_clean.vcxproj", "{02D16A66-6D59-4A0E-ABB3-BD12926934FE}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uninstall", "uninstall.vcxproj", "{B5A9B8B7-53AC-46D7-9ADE-76F708A7189C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {90BC31D7-A3E8-4F04-8049-2236C239A044}
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CMakePredefinedTargets", "CMakePredefinedTargets", "{31CE49D7-85CA-41E2-83D2-CC6962519DB6}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CTestDashboardTargets", "CTestDashboardTargets", "{BD073C58-BAED-420E-80EA-DC9F52E21AF7}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{8ECAB3CD-B434-426B-B63A-115919D393BC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{964DC7DE-990A-4CA4-8395-10D9F9CB2A23}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utilities", "Utilities", "{7E002D15-21D1-4927-B486-82E496444441}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3rdParty", "Utilities\3rdParty", "{0984A63C-130E-4B62-9A94-AAC28A88C137}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "KWSys", "Utilities\KWSys", "{EF1DFA45-6F7A-4760-8EB5-69A8A221FC54}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Win9xCompat", "Utilities\Win9xCompat", "{2485E202-B981-41E0-98CA-CF363437A4E4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ MinSizeRel|x64 = MinSizeRel|x64
+ RelWithDebInfo|x64 = RelWithDebInfo|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}.Debug|x64.ActiveCfg = Debug|x64
+ {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}.Debug|x64.Build.0 = Debug|x64
+ {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}.Release|x64.ActiveCfg = Release|x64
+ {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}.Release|x64.Build.0 = Release|x64
+ {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {BC04E6F9-A1E4-43BA-88B3-6FBF45FA561C}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}.Debug|x64.ActiveCfg = Debug|x64
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}.Debug|x64.Build.0 = Debug|x64
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}.Release|x64.ActiveCfg = Release|x64
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}.Release|x64.Build.0 = Release|x64
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {59BCCCCD-3AD1-4491-B8F4-C5793AC007E2}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {B025BD09-8389-4D9F-9150-F33418A664B1}.Debug|x64.ActiveCfg = Debug|x64
+ {B025BD09-8389-4D9F-9150-F33418A664B1}.Debug|x64.Build.0 = Debug|x64
+ {B025BD09-8389-4D9F-9150-F33418A664B1}.Release|x64.ActiveCfg = Release|x64
+ {B025BD09-8389-4D9F-9150-F33418A664B1}.Release|x64.Build.0 = Release|x64
+ {B025BD09-8389-4D9F-9150-F33418A664B1}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {B025BD09-8389-4D9F-9150-F33418A664B1}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {B025BD09-8389-4D9F-9150-F33418A664B1}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {B025BD09-8389-4D9F-9150-F33418A664B1}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}.Debug|x64.ActiveCfg = Debug|x64
+ {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}.Debug|x64.Build.0 = Debug|x64
+ {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}.Release|x64.ActiveCfg = Release|x64
+ {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}.Release|x64.Build.0 = Release|x64
+ {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {94EAABE8-174B-4EE9-8EDF-C5FED49A31B8}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {1002C8FC-7242-4A69-AF51-C59BB10BA6D8}.Debug|x64.ActiveCfg = Debug|x64
+ {1002C8FC-7242-4A69-AF51-C59BB10BA6D8}.Debug|x64.Build.0 = Debug|x64
+ {1002C8FC-7242-4A69-AF51-C59BB10BA6D8}.Release|x64.ActiveCfg = Release|x64
+ {1002C8FC-7242-4A69-AF51-C59BB10BA6D8}.Release|x64.Build.0 = Release|x64
+ {1002C8FC-7242-4A69-AF51-C59BB10BA6D8}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {1002C8FC-7242-4A69-AF51-C59BB10BA6D8}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {1002C8FC-7242-4A69-AF51-C59BB10BA6D8}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {1002C8FC-7242-4A69-AF51-C59BB10BA6D8}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}.Debug|x64.ActiveCfg = Debug|x64
+ {E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}.Release|x64.ActiveCfg = Release|x64
+ {E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {B28E8445-DFD2-46EA-BA6C-C2A1864F2FB1}.Debug|x64.ActiveCfg = Debug|x64
+ {B28E8445-DFD2-46EA-BA6C-C2A1864F2FB1}.Release|x64.ActiveCfg = Release|x64
+ {B28E8445-DFD2-46EA-BA6C-C2A1864F2FB1}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {B28E8445-DFD2-46EA-BA6C-C2A1864F2FB1}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {3B126B2D-DEAA-4CDF-9F44-28D3600F5754}.Debug|x64.ActiveCfg = Debug|x64
+ {3B126B2D-DEAA-4CDF-9F44-28D3600F5754}.Release|x64.ActiveCfg = Release|x64
+ {3B126B2D-DEAA-4CDF-9F44-28D3600F5754}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {3B126B2D-DEAA-4CDF-9F44-28D3600F5754}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {0283B293-0067-4D02-ADA6-892704398F48}.Debug|x64.ActiveCfg = Debug|x64
+ {0283B293-0067-4D02-ADA6-892704398F48}.Debug|x64.Build.0 = Debug|x64
+ {0283B293-0067-4D02-ADA6-892704398F48}.Release|x64.ActiveCfg = Release|x64
+ {0283B293-0067-4D02-ADA6-892704398F48}.Release|x64.Build.0 = Release|x64
+ {0283B293-0067-4D02-ADA6-892704398F48}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {0283B293-0067-4D02-ADA6-892704398F48}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {0283B293-0067-4D02-ADA6-892704398F48}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {0283B293-0067-4D02-ADA6-892704398F48}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {7BAF09E0-DCD4-4567-9486-79E1E5F18333}.Debug|x64.ActiveCfg = Debug|x64
+ {7BAF09E0-DCD4-4567-9486-79E1E5F18333}.Release|x64.ActiveCfg = Release|x64
+ {7BAF09E0-DCD4-4567-9486-79E1E5F18333}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {7BAF09E0-DCD4-4567-9486-79E1E5F18333}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {D0413FDA-31C5-41C2-A53A-C1B87061EC96}.Debug|x64.ActiveCfg = Debug|x64
+ {D0413FDA-31C5-41C2-A53A-C1B87061EC96}.Release|x64.ActiveCfg = Release|x64
+ {D0413FDA-31C5-41C2-A53A-C1B87061EC96}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {D0413FDA-31C5-41C2-A53A-C1B87061EC96}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {4C488FF0-7C06-47FE-A8FD-67DAD51A3E85}.Debug|x64.ActiveCfg = Debug|x64
+ {4C488FF0-7C06-47FE-A8FD-67DAD51A3E85}.Release|x64.ActiveCfg = Release|x64
+ {4C488FF0-7C06-47FE-A8FD-67DAD51A3E85}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {4C488FF0-7C06-47FE-A8FD-67DAD51A3E85}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {D87B08A8-638E-43FA-96C2-404B41363D3B}.Debug|x64.ActiveCfg = Debug|x64
+ {D87B08A8-638E-43FA-96C2-404B41363D3B}.Release|x64.ActiveCfg = Release|x64
+ {D87B08A8-638E-43FA-96C2-404B41363D3B}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {D87B08A8-638E-43FA-96C2-404B41363D3B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {90BC31D7-A3E8-4F04-8049-2236C239A044}.Debug|x64.ActiveCfg = Debug|x64
+ {90BC31D7-A3E8-4F04-8049-2236C239A044}.Debug|x64.Build.0 = Debug|x64
+ {90BC31D7-A3E8-4F04-8049-2236C239A044}.Release|x64.ActiveCfg = Release|x64
+ {90BC31D7-A3E8-4F04-8049-2236C239A044}.Release|x64.Build.0 = Release|x64
+ {90BC31D7-A3E8-4F04-8049-2236C239A044}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {90BC31D7-A3E8-4F04-8049-2236C239A044}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {90BC31D7-A3E8-4F04-8049-2236C239A044}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {90BC31D7-A3E8-4F04-8049-2236C239A044}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {48D43A03-3C1B-439A-9517-8F2A2B4CEC3B}.Debug|x64.ActiveCfg = Debug|x64
+ {48D43A03-3C1B-439A-9517-8F2A2B4CEC3B}.Debug|x64.Build.0 = Debug|x64
+ {48D43A03-3C1B-439A-9517-8F2A2B4CEC3B}.Release|x64.ActiveCfg = Release|x64
+ {48D43A03-3C1B-439A-9517-8F2A2B4CEC3B}.Release|x64.Build.0 = Release|x64
+ {48D43A03-3C1B-439A-9517-8F2A2B4CEC3B}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {48D43A03-3C1B-439A-9517-8F2A2B4CEC3B}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {48D43A03-3C1B-439A-9517-8F2A2B4CEC3B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {48D43A03-3C1B-439A-9517-8F2A2B4CEC3B}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}.Debug|x64.ActiveCfg = Debug|x64
+ {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}.Debug|x64.Build.0 = Debug|x64
+ {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}.Release|x64.ActiveCfg = Release|x64
+ {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}.Release|x64.Build.0 = Release|x64
+ {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {6ADE54B3-3FDA-4E76-9B87-66D95E5265A8}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}.Debug|x64.ActiveCfg = Debug|x64
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}.Debug|x64.Build.0 = Debug|x64
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}.Release|x64.ActiveCfg = Release|x64
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}.Release|x64.Build.0 = Release|x64
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84}.Debug|x64.ActiveCfg = Debug|x64
+ {A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84}.Debug|x64.Build.0 = Debug|x64
+ {A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84}.Release|x64.ActiveCfg = Release|x64
+ {A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84}.Release|x64.Build.0 = Release|x64
+ {A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {A51EB64E-E1EA-4B4A-8FDC-56ADFE635E84}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C}.Debug|x64.ActiveCfg = Debug|x64
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C}.Debug|x64.Build.0 = Debug|x64
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C}.Release|x64.ActiveCfg = Release|x64
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C}.Release|x64.Build.0 = Release|x64
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}.Debug|x64.ActiveCfg = Debug|x64
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}.Debug|x64.Build.0 = Debug|x64
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}.Release|x64.ActiveCfg = Release|x64
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}.Release|x64.Build.0 = Release|x64
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}.Debug|x64.ActiveCfg = Debug|x64
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}.Debug|x64.Build.0 = Debug|x64
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}.Release|x64.ActiveCfg = Release|x64
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}.Release|x64.Build.0 = Release|x64
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}.Debug|x64.ActiveCfg = Debug|x64
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}.Debug|x64.Build.0 = Debug|x64
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}.Release|x64.ActiveCfg = Release|x64
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}.Release|x64.Build.0 = Release|x64
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F}.Debug|x64.ActiveCfg = Debug|x64
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F}.Debug|x64.Build.0 = Debug|x64
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F}.Release|x64.ActiveCfg = Release|x64
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F}.Release|x64.Build.0 = Release|x64
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}.Debug|x64.ActiveCfg = Debug|x64
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}.Debug|x64.Build.0 = Debug|x64
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}.Release|x64.ActiveCfg = Release|x64
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}.Release|x64.Build.0 = Release|x64
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996}.Debug|x64.ActiveCfg = Debug|x64
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996}.Debug|x64.Build.0 = Debug|x64
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996}.Release|x64.ActiveCfg = Release|x64
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996}.Release|x64.Build.0 = Release|x64
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {A0421DCA-AC3E-42D0-94AC-379A21A1E591}.Debug|x64.ActiveCfg = Debug|x64
+ {A0421DCA-AC3E-42D0-94AC-379A21A1E591}.Debug|x64.Build.0 = Debug|x64
+ {A0421DCA-AC3E-42D0-94AC-379A21A1E591}.Release|x64.ActiveCfg = Release|x64
+ {A0421DCA-AC3E-42D0-94AC-379A21A1E591}.Release|x64.Build.0 = Release|x64
+ {A0421DCA-AC3E-42D0-94AC-379A21A1E591}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {A0421DCA-AC3E-42D0-94AC-379A21A1E591}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {A0421DCA-AC3E-42D0-94AC-379A21A1E591}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {A0421DCA-AC3E-42D0-94AC-379A21A1E591}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {C6AF7E57-CE57-4462-AE1D-BF520701480E}.Debug|x64.ActiveCfg = Debug|x64
+ {C6AF7E57-CE57-4462-AE1D-BF520701480E}.Debug|x64.Build.0 = Debug|x64
+ {C6AF7E57-CE57-4462-AE1D-BF520701480E}.Release|x64.ActiveCfg = Release|x64
+ {C6AF7E57-CE57-4462-AE1D-BF520701480E}.Release|x64.Build.0 = Release|x64
+ {C6AF7E57-CE57-4462-AE1D-BF520701480E}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {C6AF7E57-CE57-4462-AE1D-BF520701480E}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {C6AF7E57-CE57-4462-AE1D-BF520701480E}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {C6AF7E57-CE57-4462-AE1D-BF520701480E}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {F2CAAAB3-9568-4284-B8E3-13955183A6D7}.Debug|x64.ActiveCfg = Debug|x64
+ {F2CAAAB3-9568-4284-B8E3-13955183A6D7}.Debug|x64.Build.0 = Debug|x64
+ {F2CAAAB3-9568-4284-B8E3-13955183A6D7}.Release|x64.ActiveCfg = Release|x64
+ {F2CAAAB3-9568-4284-B8E3-13955183A6D7}.Release|x64.Build.0 = Release|x64
+ {F2CAAAB3-9568-4284-B8E3-13955183A6D7}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {F2CAAAB3-9568-4284-B8E3-13955183A6D7}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {F2CAAAB3-9568-4284-B8E3-13955183A6D7}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {F2CAAAB3-9568-4284-B8E3-13955183A6D7}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {D8294E4A-03C5-43D7-AE35-15603F502DC0}.Debug|x64.ActiveCfg = Debug|x64
+ {D8294E4A-03C5-43D7-AE35-15603F502DC0}.Debug|x64.Build.0 = Debug|x64
+ {D8294E4A-03C5-43D7-AE35-15603F502DC0}.Release|x64.ActiveCfg = Release|x64
+ {D8294E4A-03C5-43D7-AE35-15603F502DC0}.Release|x64.Build.0 = Release|x64
+ {D8294E4A-03C5-43D7-AE35-15603F502DC0}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {D8294E4A-03C5-43D7-AE35-15603F502DC0}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {D8294E4A-03C5-43D7-AE35-15603F502DC0}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {D8294E4A-03C5-43D7-AE35-15603F502DC0}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {A4921D15-411F-436A-B6F3-F8381652A8E1}.Debug|x64.ActiveCfg = Debug|x64
+ {A4921D15-411F-436A-B6F3-F8381652A8E1}.Debug|x64.Build.0 = Debug|x64
+ {A4921D15-411F-436A-B6F3-F8381652A8E1}.Release|x64.ActiveCfg = Release|x64
+ {A4921D15-411F-436A-B6F3-F8381652A8E1}.Release|x64.Build.0 = Release|x64
+ {A4921D15-411F-436A-B6F3-F8381652A8E1}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {A4921D15-411F-436A-B6F3-F8381652A8E1}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {A4921D15-411F-436A-B6F3-F8381652A8E1}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {A4921D15-411F-436A-B6F3-F8381652A8E1}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}.Debug|x64.ActiveCfg = Debug|x64
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}.Debug|x64.Build.0 = Debug|x64
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}.Release|x64.ActiveCfg = Release|x64
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}.Release|x64.Build.0 = Release|x64
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C}.Debug|x64.ActiveCfg = Debug|x64
+ {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C}.Debug|x64.Build.0 = Debug|x64
+ {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C}.Release|x64.ActiveCfg = Release|x64
+ {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C}.Release|x64.Build.0 = Release|x64
+ {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}.Debug|x64.ActiveCfg = Debug|x64
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}.Debug|x64.Build.0 = Debug|x64
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}.Release|x64.ActiveCfg = Release|x64
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}.Release|x64.Build.0 = Release|x64
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {0E9E295F-3854-415B-AE9F-7B62F17932F5}.Debug|x64.ActiveCfg = Debug|x64
+ {0E9E295F-3854-415B-AE9F-7B62F17932F5}.Debug|x64.Build.0 = Debug|x64
+ {0E9E295F-3854-415B-AE9F-7B62F17932F5}.Release|x64.ActiveCfg = Release|x64
+ {0E9E295F-3854-415B-AE9F-7B62F17932F5}.Release|x64.Build.0 = Release|x64
+ {0E9E295F-3854-415B-AE9F-7B62F17932F5}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {0E9E295F-3854-415B-AE9F-7B62F17932F5}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {0E9E295F-3854-415B-AE9F-7B62F17932F5}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {0E9E295F-3854-415B-AE9F-7B62F17932F5}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {4BFA4D7C-C6F7-4270-9E87-B922DCE05644}.Debug|x64.ActiveCfg = Debug|x64
+ {4BFA4D7C-C6F7-4270-9E87-B922DCE05644}.Debug|x64.Build.0 = Debug|x64
+ {4BFA4D7C-C6F7-4270-9E87-B922DCE05644}.Release|x64.ActiveCfg = Release|x64
+ {4BFA4D7C-C6F7-4270-9E87-B922DCE05644}.Release|x64.Build.0 = Release|x64
+ {4BFA4D7C-C6F7-4270-9E87-B922DCE05644}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {4BFA4D7C-C6F7-4270-9E87-B922DCE05644}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {4BFA4D7C-C6F7-4270-9E87-B922DCE05644}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {4BFA4D7C-C6F7-4270-9E87-B922DCE05644}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {F77AD922-B4BC-43D7-B268-865312085495}.Debug|x64.ActiveCfg = Debug|x64
+ {F77AD922-B4BC-43D7-B268-865312085495}.Debug|x64.Build.0 = Debug|x64
+ {F77AD922-B4BC-43D7-B268-865312085495}.Release|x64.ActiveCfg = Release|x64
+ {F77AD922-B4BC-43D7-B268-865312085495}.Release|x64.Build.0 = Release|x64
+ {F77AD922-B4BC-43D7-B268-865312085495}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {F77AD922-B4BC-43D7-B268-865312085495}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {F77AD922-B4BC-43D7-B268-865312085495}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {F77AD922-B4BC-43D7-B268-865312085495}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88}.Debug|x64.ActiveCfg = Debug|x64
+ {8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88}.Debug|x64.Build.0 = Debug|x64
+ {8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88}.Release|x64.ActiveCfg = Release|x64
+ {8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88}.Release|x64.Build.0 = Release|x64
+ {8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {8DF3790D-AF1B-4505-BA5B-4D61EF9FBE88}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {1DFA0599-77CC-4768-B47A-107EEE86C20C}.Debug|x64.ActiveCfg = Debug|x64
+ {1DFA0599-77CC-4768-B47A-107EEE86C20C}.Debug|x64.Build.0 = Debug|x64
+ {1DFA0599-77CC-4768-B47A-107EEE86C20C}.Release|x64.ActiveCfg = Release|x64
+ {1DFA0599-77CC-4768-B47A-107EEE86C20C}.Release|x64.Build.0 = Release|x64
+ {1DFA0599-77CC-4768-B47A-107EEE86C20C}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {1DFA0599-77CC-4768-B47A-107EEE86C20C}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {1DFA0599-77CC-4768-B47A-107EEE86C20C}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {1DFA0599-77CC-4768-B47A-107EEE86C20C}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {0E45A3EF-8636-46CF-94A3-7B5CE875DE48}.Debug|x64.ActiveCfg = Debug|x64
+ {0E45A3EF-8636-46CF-94A3-7B5CE875DE48}.Debug|x64.Build.0 = Debug|x64
+ {0E45A3EF-8636-46CF-94A3-7B5CE875DE48}.Release|x64.ActiveCfg = Release|x64
+ {0E45A3EF-8636-46CF-94A3-7B5CE875DE48}.Release|x64.Build.0 = Release|x64
+ {0E45A3EF-8636-46CF-94A3-7B5CE875DE48}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {0E45A3EF-8636-46CF-94A3-7B5CE875DE48}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {0E45A3EF-8636-46CF-94A3-7B5CE875DE48}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {0E45A3EF-8636-46CF-94A3-7B5CE875DE48}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C}.Debug|x64.ActiveCfg = Debug|x64
+ {CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C}.Debug|x64.Build.0 = Debug|x64
+ {CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C}.Release|x64.ActiveCfg = Release|x64
+ {CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C}.Release|x64.Build.0 = Release|x64
+ {CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {CAEF2D10-B14D-4E0C-8B79-8AC767B12F7C}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {02D16A66-6D59-4A0E-ABB3-BD12926934FE}.Debug|x64.ActiveCfg = Debug|x64
+ {02D16A66-6D59-4A0E-ABB3-BD12926934FE}.Release|x64.ActiveCfg = Release|x64
+ {02D16A66-6D59-4A0E-ABB3-BD12926934FE}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {02D16A66-6D59-4A0E-ABB3-BD12926934FE}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {B5A9B8B7-53AC-46D7-9ADE-76F708A7189C}.Debug|x64.ActiveCfg = Debug|x64
+ {B5A9B8B7-53AC-46D7-9ADE-76F708A7189C}.Release|x64.ActiveCfg = Release|x64
+ {B5A9B8B7-53AC-46D7-9ADE-76F708A7189C}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {B5A9B8B7-53AC-46D7-9ADE-76F708A7189C}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {3B126B2D-DEAA-4CDF-9F44-28D3600F5754} = {31CE49D7-85CA-41E2-83D2-CC6962519DB6}
+ {4C488FF0-7C06-47FE-A8FD-67DAD51A3E85} = {31CE49D7-85CA-41E2-83D2-CC6962519DB6}
+ {D87B08A8-638E-43FA-96C2-404B41363D3B} = {31CE49D7-85CA-41E2-83D2-CC6962519DB6}
+ {90BC31D7-A3E8-4F04-8049-2236C239A044} = {31CE49D7-85CA-41E2-83D2-CC6962519DB6}
+ {E5071092-DBFB-49E2-AF0F-E8B0FDEF6C89} = {BD073C58-BAED-420E-80EA-DC9F52E21AF7}
+ {B28E8445-DFD2-46EA-BA6C-C2A1864F2FB1} = {BD073C58-BAED-420E-80EA-DC9F52E21AF7}
+ {7BAF09E0-DCD4-4567-9486-79E1E5F18333} = {BD073C58-BAED-420E-80EA-DC9F52E21AF7}
+ {D0413FDA-31C5-41C2-A53A-C1B87061EC96} = {BD073C58-BAED-420E-80EA-DC9F52E21AF7}
+ {F77AD922-B4BC-43D7-B268-865312085495} = {8ECAB3CD-B434-426B-B63A-115919D393BC}
+ {B025BD09-8389-4D9F-9150-F33418A664B1} = {964DC7DE-990A-4CA4-8395-10D9F9CB2A23}
+ {0984A63C-130E-4B62-9A94-AAC28A88C137} = {7E002D15-21D1-4927-B486-82E496444441}
+ {EF1DFA45-6F7A-4760-8EB5-69A8A221FC54} = {7E002D15-21D1-4927-B486-82E496444441}
+ {2485E202-B981-41E0-98CA-CF363437A4E4} = {7E002D15-21D1-4927-B486-82E496444441}
+ {0283B293-0067-4D02-ADA6-892704398F48} = {0984A63C-130E-4B62-9A94-AAC28A88C137}
+ {1C5345F9-9C47-4F4B-9760-7A74C9D35DE0} = {0984A63C-130E-4B62-9A94-AAC28A88C137}
+ {561AD1BB-6DD3-466D-B270-3696DEE8C26C} = {0984A63C-130E-4B62-9A94-AAC28A88C137}
+ {1342243A-C3D9-45A0-B4BC-65A8F16BCC9D} = {0984A63C-130E-4B62-9A94-AAC28A88C137}
+ {459BD82A-588C-4BFD-B3E6-1E4E3BC1B1E3} = {0984A63C-130E-4B62-9A94-AAC28A88C137}
+ {25A91A7A-9C4E-420C-98BD-2D1F0165DA54} = {0984A63C-130E-4B62-9A94-AAC28A88C137}
+ {0B7FB622-7A90-490C-B4E4-2DE3112BB5E0} = {0984A63C-130E-4B62-9A94-AAC28A88C137}
+ {BDB424DC-15B3-4A06-A1E2-3D61380F359F} = {EF1DFA45-6F7A-4760-8EB5-69A8A221FC54}
+ {4810B052-899E-4CA5-A0BC-2E383F8AEFAE} = {EF1DFA45-6F7A-4760-8EB5-69A8A221FC54}
+ {29D5FCAF-20D0-4DEF-8529-F035C249E996} = {EF1DFA45-6F7A-4760-8EB5-69A8A221FC54}
+ {A0421DCA-AC3E-42D0-94AC-379A21A1E591} = {EF1DFA45-6F7A-4760-8EB5-69A8A221FC54}
+ {C6AF7E57-CE57-4462-AE1D-BF520701480E} = {EF1DFA45-6F7A-4760-8EB5-69A8A221FC54}
+ {F2CAAAB3-9568-4284-B8E3-13955183A6D7} = {EF1DFA45-6F7A-4760-8EB5-69A8A221FC54}
+ {D8294E4A-03C5-43D7-AE35-15603F502DC0} = {EF1DFA45-6F7A-4760-8EB5-69A8A221FC54}
+ {A4921D15-411F-436A-B6F3-F8381652A8E1} = {EF1DFA45-6F7A-4760-8EB5-69A8A221FC54}
+ {60BEB3AF-B4EF-4363-8747-C40177BC2D9C} = {EF1DFA45-6F7A-4760-8EB5-69A8A221FC54}
+ {ACC30B92-8B65-4A9D-9BF2-6BBD0B008C8C} = {2485E202-B981-41E0-98CA-CF363437A4E4}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 44e9450a4..9c3ed594f 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -225,6 +225,7 @@ if(BUILD_TESTING) ADD_TEST_MACRO(ObjectLibrary UseCshared) ADD_TEST_MACRO(NewlineArgs NewlineArgs) ADD_TEST_MACRO(SetLang SetLang) + ADD_TEST_MACRO(EmptyProperty EmptyProperty) ADD_TEST_MACRO(ExternalOBJ ExternalOBJ) ADD_TEST_MACRO(LoadCommand LoadedCommand) ADD_TEST_MACRO(LinkDirectory bin/LinkDirectory) @@ -242,9 +243,11 @@ if(BUILD_TESTING) ADD_TEST_MACRO(PolicyScope PolicyScope) ADD_TEST_MACRO(EmptyLibrary EmptyLibrary) ADD_TEST_MACRO(CompileDefinitions CompileDefinitions) + ADD_TEST_MACRO(CompileOptions CompileOptions) ADD_TEST_MACRO(CompatibleInterface CompatibleInterface) + ADD_TEST_MACRO(AliasTarget AliasTarget) set_tests_properties(EmptyLibrary PROPERTIES - PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target:test") + PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test") ADD_TEST_MACRO(CrossCompile CrossCompile) set_tests_properties(CrossCompile PROPERTIES PASS_REGULAR_EXPRESSION "TRY_RUN.. invoked in cross-compiling mode") @@ -392,10 +395,20 @@ if(BUILD_TESTING) endmacro() ADD_LINK_FLAGS_TEST(lib prepare) ADD_LINK_FLAGS_TEST(dll lib) - ADD_LINK_FLAGS_TEST(exe dll) + ADD_LINK_FLAGS_TEST(mod dll) + ADD_LINK_FLAGS_TEST(exe mod) ADD_LINK_FLAGS_TEST(lib_config exe) ADD_LINK_FLAGS_TEST(dll_config lib_config) - ADD_LINK_FLAGS_TEST(exe_config dll_config) + ADD_LINK_FLAGS_TEST(mod_config dll_config) + ADD_LINK_FLAGS_TEST(exe_config mod_config) + ADD_LINK_FLAGS_TEST(lib_flags exe_config) + ADD_LINK_FLAGS_TEST(dll_flags lib_flags) + ADD_LINK_FLAGS_TEST(mod_flags dll_flags) + ADD_LINK_FLAGS_TEST(exe_flags mod_flags) + ADD_LINK_FLAGS_TEST(lib_flags_config exe_flags) + ADD_LINK_FLAGS_TEST(dll_flags_config lib_flags_config) + ADD_LINK_FLAGS_TEST(mod_flags_config dll_flags_config) + ADD_LINK_FLAGS_TEST(exe_flags_config mod_flags_config) # If we are running right now with a UnixMakefiles based generator, # build the "Simple" test with the ExtraGenerators, if available @@ -1000,21 +1013,35 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomocNoQt") - if(QT4_WORKS AND QT_QTGUI_FOUND) - add_test(QtAutomoc ${CMAKE_CTEST_COMMAND} + find_package(Qt5Widgets QUIET NO_MODULE) + if(Qt5Widgets_FOUND) + add_test(Qt5Automoc ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/QtAutomoc" - "${CMake_BINARY_DIR}/Tests/QtAutomoc" + "${CMake_BINARY_DIR}/Tests/Qt5Automoc" ${build_generator_args} --build-project QtAutomoc - --build-exe-dir "${CMake_BINARY_DIR}/Tests/QtAutomoc" + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt5Automoc" --force-new-ctest-process - --build-options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} + --build-options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} -DQT_TEST_VERSION=5 --test-command ${CMAKE_CTEST_COMMAND} -V ) - list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomoc") + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt5Automoc") endif() if(QT4_WORKS AND QT_QTGUI_FOUND) + add_test(Qt4Automoc ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/QtAutomoc" + "${CMake_BINARY_DIR}/Tests/Qt4Automoc" + ${build_generator_args} + --build-project QtAutomoc + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4Automoc" + --force-new-ctest-process + --build-options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} -DQT_TEST_VERSION=4 + --test-command ${CMAKE_CTEST_COMMAND} -V + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4Automoc") + add_test(Qt4Targets ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/Qt4Targets" @@ -1027,6 +1054,20 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ --test-command ${CMAKE_CTEST_COMMAND} -V ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4Targets") + + if(Qt5Widgets_FOUND AND NOT Qt5Widgets_VERSION VERSION_LESS 5.1.0) + add_test(Qt4And5Automoc ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/Qt4And5Automoc" + "${CMake_BINARY_DIR}/Tests/Qt4And5Automoc" + ${build_generator_args} + --build-project Qt4And5Automoc + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4And5Automoc" + --force-new-ctest-process + --test-command ${CMAKE_CTEST_COMMAND} -V + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4And5Automoc") + endif() endif() add_test(ExternalProject ${CMAKE_CTEST_COMMAND} @@ -1216,6 +1257,16 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ endif() endif() + if(APPLE AND "${DARWIN_MAJOR_VERSION}" GREATER 9) + add_test(MacRuntimePath ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/MacRuntimePath" + "${CMake_BINARY_DIR}/Tests/MacRuntimePath" + ${build_generator_args} + --build-project MacRuntimePath + ) + endif() + add_test(linkorder1 ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/LinkLineOrder" @@ -1445,6 +1496,11 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ADD_TEST_MACRO(SBCS SBCS) endif() + if(NOT "${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [6789]( |$)" + AND NOT CMAKE_TEST_GENERATOR_TOOLSET) + ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx) + endif() + add_test(VSExternalInclude ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/VSExternalInclude" @@ -1492,6 +1548,34 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ unset(_last_test) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/VSExcludeFromDefaultBuild") endif() + + if(CMAKE_TEST_GENERATOR MATCHES "Visual Studio ([0-5]|[6-9][0-9])") + if(CMAKE_TEST_MAKEPROGRAM MATCHES "[mM][sS][bB][uU][iI][lL][dD]\\.[eE][xX][eE]") + set(MSBUILD_EXECUTABLE "${CMAKE_TEST_MAKEPROGRAM}") + else() + if(CMAKE_TEST_GENERATOR MATCHES "Visual Studio (12)") + set(_msbuild_hints "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\${CMAKE_MATCH_1}.0;MSBuildToolsPath]") + else() + set(_FDIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7;FrameworkDir32]") + set(_FVER "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7;FrameworkVer32]") + set(_msbuild_hints ${_FDIR}/${_FVER}) + endif() + find_program(MSBUILD_EXECUTABLE NAMES msbuild HINTS ${_msbuild_hints}) + endif() + if(MSBUILD_EXECUTABLE) + add_test(NAME VSProjectInSubdir COMMAND ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/VSProjectInSubdir" + "${CMake_BINARY_DIR}/Tests/VSProjectInSubdir" + --build-two-config + --build-generator ${CMAKE_TEST_GENERATOR} + --build-generator-toolset "${CMAKE_TEST_GENERATOR_TOOLSET}" + --build-makeprogram "${MSBUILD_EXECUTABLE}" + --build-project VSProjectInSubdir + --build-target test) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/VSProjectInSubdir") + endif() + endif() endif() if (APPLE) @@ -1573,17 +1657,23 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ FAIL_REGULAR_EXPRESSION "CMake Warning .*VariableUnusedViaUnset.CMakeLists.txt:5 \\(set\\):") list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/WarnUnusedUnusedViaUnset") - add_test(WarnUnusedCliUnused ${CMAKE_CTEST_COMMAND} - --build-and-test - "${CMake_SOURCE_DIR}/Tests/VariableUsage" - "${CMake_BINARY_DIR}/Tests/WarnUnusedCliUnused" - ${build_generator_args} - --build-noclean - --build-project WarnUnusedCliUnused - --build-options "-DUNUSED_CLI_VARIABLE=Unused") - set_tests_properties(WarnUnusedCliUnused PROPERTIES - PASS_REGULAR_EXPRESSION "CMake Warning:.*Manually-specified variables were not used by the project:.* UNUSED_CLI_VARIABLE") - list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/WarnUnusedCliUnused") + if("${CMAKE_TEST_GENERATOR}" MATCHES "Makefile" AND NOT WIN32) + # Ninja does not support ADDITIONAL_MAKE_CLEAN_FILES and therefore fails + # this test. (See #13371) + # Apparently Visual Studio does not support it either. As the MakeClean + # test above is only run with the Makefiles generator, only run this + # test with the Makefiles generator also. + add_test(WarnUnusedCliUnused ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/WarnUnusedCliUnused" + "${CMake_BINARY_DIR}/Tests/WarnUnusedCliUnused" + ${build_generator_args} + --build-project WarnUnusedCliUnused + --build-options "-DUNUSED_CLI_VARIABLE=Unused") + set_tests_properties(WarnUnusedCliUnused PROPERTIES + PASS_REGULAR_EXPRESSION "CMake Warning:.*Manually-specified variables were not used by the project:.* UNUSED_CLI_VARIABLE") + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/WarnUnusedCliUnused") + endif() add_test(WarnUnusedCliUsed ${CMAKE_CTEST_COMMAND} --build-and-test @@ -1634,6 +1724,20 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ # -S "${CMake_BINARY_DIR}/Tests/CTestScriptMode/CTestTestScriptMode.cmake" # ) + # A test for ctest_build() with targets in subdirectories + if(CMAKE_TEST_GENERATOR_TOOLSET) + set(CMAKE_TEST_GENERATOR_TOOLSET_SELECTION "-T;${CMAKE_TEST_GENERATOR_TOOLSET};") + else() + set(CMAKE_TEST_GENERATOR_TOOLSET_SELECTION) + endif() + configure_file("${CMake_SOURCE_DIR}/Tests/CTestBuildCommandProjectInSubdir/CTestBuildCommandProjectInSubdir.cmake.in" + "${CMake_BINARY_DIR}/Tests/CTestBuildCommandProjectInSubdir/CTestBuildCommandProjectInSubdir.cmake" @ONLY) + unset(CMAKE_TEST_GENERATOR_TOOLSET_SELECTION) + add_test(CTest.BuildCommand.ProjectInSubdir + ${CMAKE_CTEST_COMMAND} -S "${CMake_BINARY_DIR}/Tests/CTestBuildCommandProjectInSubdir/CTestBuildCommandProjectInSubdir.cmake" + -DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_TEST_MAKEPROGRAM}) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CTestBuildCommandProjectInSubdir/Nested") + set(CTEST_TEST_UPDATE 1) if(CTEST_TEST_UPDATE) # Test CTest Update with Subversion @@ -1907,6 +2011,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries) ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories) ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions) + ADD_TEST_MACRO(CMakeCommands.target_compile_options target_compile_options) configure_file( "${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in" @@ -1951,9 +2056,11 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ --output-log "${CMake_BINARY_DIR}/Tests/CTestTestParallel/testOutput.log" ) - set(CTestLimitDashJ_EXTRA_OPTIONS --force-new-ctest-process) - add_test_macro(CTestLimitDashJ ${CMAKE_CTEST_COMMAND} -j 4 - --output-on-failure -C "\${CTestTest_CONFIG}") + if(NOT BORLAND) + set(CTestLimitDashJ_EXTRA_OPTIONS --force-new-ctest-process) + add_test_macro(CTestLimitDashJ ${CMAKE_CTEST_COMMAND} -j 4 + --output-on-failure -C "\${CTestTest_CONFIG}") + endif() add_test(CTestTestPrintLabels ${CMAKE_CTEST_COMMAND} --print-labels) set_tests_properties(CTestTestPrintLabels PROPERTIES LABELS "Label1;Label2") @@ -2082,6 +2189,15 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ add_test(CTestBatchTest ${CMAKE_CTEST_COMMAND} -B) + configure_file( + "${CMake_SOURCE_DIR}/Tests/CTestTestFdSetSize/test.cmake.in" + "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/test.cmake" + @ONLY ESCAPE_QUOTES) + add_test(CTestTestFdSetSize ${CMAKE_CTEST_COMMAND} + -S "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/test.cmake" -j20 -V --timeout 120 + --output-log "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/testOutput.log" + ) + # Use macro, not function so that build can still be driven by CMake 2.4. # After 2.6 is required, this could be a function without the extra 'set' # calls. @@ -2426,6 +2542,16 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ --test-command IncludeDirectories) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/IncludeDirectories") + add_test(InterfaceLinkLibraries ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/InterfaceLinkLibraries" + "${CMake_BINARY_DIR}/Tests/InterfaceLinkLibraries" + --build-two-config + ${build_generator_args} + --build-project InterfaceLinkLibraries + --test-command InterfaceLinkLibraries) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/InterfaceLinkLibraries") + if(CMAKE_USE_KWSTYLE AND KWSTYLE_EXECUTABLE) # The "make StyleCheck" command line as a test. If the test fails, look # for lines like "Error #0 (624) Line length exceed 88 (max=79)" in the diff --git a/Tests/CMakeOnly/SelectLibraryConfigurations/CMakeLists.txt b/Tests/CMakeOnly/SelectLibraryConfigurations/CMakeLists.txt index 5bf0f8abc..6d1628ae5 100644 --- a/Tests/CMakeOnly/SelectLibraryConfigurations/CMakeLists.txt +++ b/Tests/CMakeOnly/SelectLibraryConfigurations/CMakeLists.txt @@ -29,7 +29,7 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug) endif () -check_slc(empty "") +check_slc(empty "empty_LIBRARY-NOTFOUND") set(OPTONLY_LIBRARY_RELEASE "opt") check_slc(OPTONLY "opt") diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake new file mode 100644 index 000000000..1655eb406 --- /dev/null +++ b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake @@ -0,0 +1 @@ +cmake_host_system_information(HOSTNAME) diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake new file mode 100644 index 000000000..1f056d5f2 --- /dev/null +++ b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake @@ -0,0 +1 @@ +cmake_host_system_information(RESULT FQDN HOSTNAME) diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake new file mode 100644 index 000000000..9c5a558c7 --- /dev/null +++ b/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake @@ -0,0 +1 @@ +cmake_host_system_information(RESULT RESULT QUERY FOOBAR) diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake b/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake new file mode 100644 index 000000000..1c3156d23 --- /dev/null +++ b/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake @@ -0,0 +1,5 @@ +cmake_host_system_information(RESULT RESULT + QUERY NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES +) + +message("[${RESULT}]") diff --git a/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in b/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in new file mode 100644 index 000000000..3294a2f0d --- /dev/null +++ b/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in @@ -0,0 +1,33 @@ +set(BadArg1-RESULT 1) +set(BadArg1-STDERR "missing RESULT specification") +set(BadArg2-RESULT 1) +set(BadArg2-STDERR "missing QUERY specification") +set(BadArg3-RESULT 1) +set(BadArg3-STDERR "does not recognize <key> FOOBAR") +set(QueryList-RESULT 0) +set(QueryList-STDERR "\\[[0-9]+;[0-9]+\\]") + +function(try_and_print key) + cmake_host_system_information(RESULT RESULT QUERY ${key}) + message(STATUS "[${key}] [${RESULT}]") +endfunction() + +message("CTEST_FULL_OUTPUT (Avoid ctest truncation of output)") + +try_and_print(NUMBER_OF_LOGICAL_CORES) +try_and_print(NUMBER_OF_PHYSICAL_CORES) +try_and_print(HOSTNAME) +try_and_print(FQDN) +try_and_print(TOTAL_VIRTUAL_MEMORY) +try_and_print(AVAILABLE_VIRTUAL_MEMORY) +try_and_print(TOTAL_PHYSICAL_MEMORY) +try_and_print(AVAILABLE_PHYSICAL_MEMORY) + +include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake") + +check_cmake_test(CMakeHostSystemInformation + BadArg1 + BadArg2 + BadArg3 + QueryList +) diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index b0499954b..344b77255 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -32,6 +32,7 @@ AddCMakeTest(CompilerIdVendor "") AddCMakeTest(ProcessorCount "-DKWSYS_TEST_EXE=$<TARGET_FILE:cmsysTestsCxx>") AddCMakeTest(PushCheckState "") AddCMakeTest(While "") +AddCMakeTest(CMakeHostSystemInformation "") AddCMakeTest(FileDownload "") set_property(TEST CMake.FileDownload PROPERTY diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index e28d102c2..055b183d6 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -508,6 +508,7 @@ list(APPEND platforms msys_g77) #----------------------------------------------------------------------------- # Test parsing for all above examples. +set(CMAKE_LINKER "not-a-linker[]().*+^$?") foreach(p IN LISTS platforms) cmake_parse_implicit_link_info("${${p}_text}" libs dirs fwks log "${${p}_obj_regex}") diff --git a/Tests/CPackWiXGenerator/CMakeLists.txt b/Tests/CPackWiXGenerator/CMakeLists.txt index ce02f110d..475e60d09 100644 --- a/Tests/CPackWiXGenerator/CMakeLists.txt +++ b/Tests/CPackWiXGenerator/CMakeLists.txt @@ -35,6 +35,8 @@ set(CPACK_PACKAGE_VERSION_PATCH "0") set(CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example") set(CPACK_WIX_UPGRADE_GUID "BF20CE5E-7F7C-401D-8F7C-AB45E8D170E6") +set(CPACK_WIX_UNINSTALL "1") +set(CPACK_PACKAGE_EXECUTABLES "mylibapp; CPack Wix Test") include(CPack) diff --git a/Tests/CTestBuildCommandProjectInSubdir/CTestBuildCommandProjectInSubdir.cmake.in b/Tests/CTestBuildCommandProjectInSubdir/CTestBuildCommandProjectInSubdir.cmake.in new file mode 100644 index 000000000..ea48c780f --- /dev/null +++ b/Tests/CTestBuildCommandProjectInSubdir/CTestBuildCommandProjectInSubdir.cmake.in @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.8.10) + +set(CTEST_SOURCE_DIRECTORY "@CMake_SOURCE_DIR@/Tests/VSProjectInSubdir") +set(CTEST_BINARY_DIRECTORY "@CMake_BINARY_DIR@/Tests/CTestBuildCommandProjectInSubdir/Nested") +set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") +set(CTEST_PROJECT_NAME "VSProjectInSubdir") +set(CTEST_BUILD_CONFIGURATION "@CTestTest_CONFIG@") + +ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) +ctest_start(Experimental) +ctest_configure(OPTIONS "@CMAKE_TEST_GENERATOR_TOOLSET_SELECTION@-DCMAKE_MAKE_PROGRAM:FILEPATH=@CMAKE_TEST_MAKEPROGRAM@") +ctest_build(TARGET test) diff --git a/Tests/CTestTestDepends/CMakeLists.txt b/Tests/CTestTestDepends/CMakeLists.txt index 26367a658..5cd6d6665 100644 --- a/Tests/CTestTestDepends/CMakeLists.txt +++ b/Tests/CTestTestDepends/CMakeLists.txt @@ -3,7 +3,8 @@ project(CTestTestDepends) include(CTest) add_executable (simple simple.cxx) -add_test (one simple) +add_executable (TestExe::Simple ALIAS simple) +add_test (NAME one COMMAND TestExe::Simple) add_test (two simple) add_test (three simple) diff --git a/Tests/CTestTestFdSetSize/CMakeLists.txt b/Tests/CTestTestFdSetSize/CMakeLists.txt new file mode 100644 index 000000000..f3827460d --- /dev/null +++ b/Tests/CTestTestFdSetSize/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required (VERSION 2.8.10) +project (CTestTestFdSetSize) +include (CTest) + +add_executable (Sleep sleep.c) + +foreach (index RANGE 1 20) + add_test (TestSleep${index} Sleep) +endforeach () diff --git a/Tests/CTestTestFdSetSize/CTestConfig.cmake b/Tests/CTestTestFdSetSize/CTestConfig.cmake new file mode 100644 index 000000000..b5f3c3363 --- /dev/null +++ b/Tests/CTestTestFdSetSize/CTestConfig.cmake @@ -0,0 +1 @@ +set(CTEST_PROJECT_NAME "CTestTestFdSetSize") diff --git a/Tests/CTestTestFdSetSize/sleep.c b/Tests/CTestTestFdSetSize/sleep.c new file mode 100644 index 000000000..b2e6a8756 --- /dev/null +++ b/Tests/CTestTestFdSetSize/sleep.c @@ -0,0 +1,16 @@ +#if defined(_WIN32) +# include <windows.h> +#else +# include <unistd.h> +#endif + +/* sleeps for 0.1 second */ +int main(int argc, char** argv) +{ +#if defined(_WIN32) + Sleep(100); +#else + usleep(100 * 1000); +#endif + return 0; +} diff --git a/Tests/CTestTestFdSetSize/test.cmake.in b/Tests/CTestTestFdSetSize/test.cmake.in new file mode 100644 index 000000000..c24f50590 --- /dev/null +++ b/Tests/CTestTestFdSetSize/test.cmake.in @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 2.8.10) + +# Settings: +set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest") +set(CTEST_SITE "@SITE@") +set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-FdSetSize") + +set(CTEST_SOURCE_DIRECTORY "@CMake_SOURCE_DIR@/Tests/CTestTestFdSetSize") +set(CTEST_BINARY_DIRECTORY "@CMake_BINARY_DIR@/Tests/CTestTestFdSetSize") +set(CTEST_CVS_COMMAND "@CVSCOMMAND@") +set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") +set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") +set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") +set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") +set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") + +ctest_start(Experimental) +ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) +message("build") +ctest_build(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) +message("test") +ctest_test(BUILD "${CTEST_BINARY_DIRECTORY}" PARALLEL_LEVEL 20 RETURN_VALUE res) +message("done") diff --git a/Tests/CTestTestMemcheck/CMakeLists.txt b/Tests/CTestTestMemcheck/CMakeLists.txt index b5f758bda..86d73854b 100644 --- a/Tests/CTestTestMemcheck/CMakeLists.txt +++ b/Tests/CTestTestMemcheck/CMakeLists.txt @@ -1,12 +1,15 @@ REGEX_ESCAPE_STRING(CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") foreach (_retval 0 1) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ret${_retval}.c" "int main(){return ${_retval};}\n") + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/memtester.cxx.in" "${CMAKE_CURRENT_BINARY_DIR}/ret${_retval}.cxx" @ONLY) endforeach () +include_directories(${CMake_SOURCE_DIR}/Source ${CMake_BINARY_DIR}/Source) + # create binaries that we will use as a pseudo memory checker -add_executable(pseudo_valgrind "${CMAKE_CURRENT_BINARY_DIR}/ret0.c") +add_executable(pseudo_valgrind "${CMAKE_CURRENT_BINARY_DIR}/ret0.cxx") set_target_properties(pseudo_valgrind PROPERTIES OUTPUT_NAME valgrind) +target_link_libraries(pseudo_valgrind CMakeLib) # Xcode 2.x forgets to create the output directory before linking # the individual architectures. @@ -16,54 +19,134 @@ if(CMAKE_OSX_ARCHITECTURES AND XCODE AND NOT "${XCODE_VERSION}" MATCHES "^[^12]" ) endif() -add_executable(pseudo_purify "${CMAKE_CURRENT_BINARY_DIR}/ret0.c") +add_executable(pseudo_purify "${CMAKE_CURRENT_BINARY_DIR}/ret0.cxx") set_target_properties(pseudo_purify PROPERTIES OUTPUT_NAME purify) -add_executable(pseudo_BC "${CMAKE_CURRENT_BINARY_DIR}/ret0.c") +target_link_libraries(pseudo_purify CMakeLib) +add_executable(pseudo_BC "${CMAKE_CURRENT_BINARY_DIR}/ret0.cxx") set_target_properties(pseudo_BC PROPERTIES OUTPUT_NAME BC) +target_link_libraries(pseudo_BC CMakeLib) # binary to be used as pre- and post-memcheck command that fails -add_executable(memcheck_fail "${CMAKE_CURRENT_BINARY_DIR}/ret1.c") - -foreach (_test IN ITEMS Unknown UnknownQuoted NotExist - DummyValgrind DummyValgrindPrePost - DummyValgrindFailPre DummyValgrindFailPost - DummyPurify DummyBC - DummyValgrindIgnoreMemcheck) - configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/${_test}/test.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/${_test}/test.cmake" - @ONLY ESCAPE_QUOTES) - add_test(NAME CTestTestMemcheck${_test} +add_executable(memcheck_fail "${CMAKE_CURRENT_BINARY_DIR}/ret1.cxx") +target_link_libraries(memcheck_fail CMakeLib) + +# Binaries that are used as memchecker that do not write the expected +# output file. Need to be in their own subdirectory as they have the +# same filenames. +add_subdirectory(NoLogDummyChecker) + +if (APPLE) + # filter out additional messages by Guard Malloc integrated in Xcode + set(GUARD_MALLOC_MSG "(ctest\([0-9]+\) malloc: [^\n]*\n)*") + set(NORMAL_CTEST_OUTPUT "\n1/1 MemCheck #1: RunCMake \\.+ Passed +[0-9]+\\.[0-9]+ sec\n${GUARD_MALLOC_MSG}\n${GUARD_MALLOC_MSG}100% tests passed, 0 tests failed out of 1\n.*\n-- Processing memory checking output: \n${GUARD_MALLOC_MSG}Memory checking results:\n${GUARD_MALLOC_MSG}") +else () + set(NORMAL_CTEST_OUTPUT "\n1/1 MemCheck #1: RunCMake \\.+ Passed +[0-9]+\\.[0-9]+ sec\n\n100% tests passed, 0 tests failed out of 1\n.*\n-- Processing memory checking output: \nMemory checking results:\n") +endif () +set(BULLSEYE_MSG "(BullseyeCoverage[^\n]*\n)?") + +function(gen_mc_test_internal NAME CHECKER) + set(SUBTEST_NAME "${NAME}") + set(CHECKER_COMMAND "${CHECKER}") + foreach(_file IN ITEMS CMakeLists.txt CTestConfig.cmake test.cmake) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${_file}.in" + "${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${_file}" @ONLY) + endforeach() + add_test(NAME CTestTestMemcheck${NAME} COMMAND ${CMAKE_CTEST_COMMAND} - -S "${CMAKE_CURRENT_BINARY_DIR}/${_test}/test.cmake" -V - --output-log "${CMAKE_CURRENT_BINARY_DIR}/${_test}/testOutput.log" + -C $<CONFIGURATION> + -S "${CMAKE_CURRENT_BINARY_DIR}/${NAME}/test.cmake" -V + --output-log "${CMAKE_CURRENT_BINARY_DIR}/${NAME}/testOutput.log" + ${ARGN} + ) +endfunction(gen_mc_test_internal) + +function(gen_mc_test NAME CHECKER) + gen_mc_test_internal(${NAME} "${CHECKER}" -D PSEUDO_BC=$<TARGET_FILE:pseudo_BC> -D PSEUDO_PURIFY=$<TARGET_FILE:pseudo_purify> -D PSEUDO_VALGRIND=$<TARGET_FILE:pseudo_valgrind> -D ERROR_COMMAND=$<TARGET_FILE:memcheck_fail> + ${ARGN} ) -endforeach () +endfunction(gen_mc_test) + +function(gen_mcnl_test NAME CHECKER) + gen_mc_test_internal(${NAME} ${CHECKER} + -D PSEUDO_BC=$<TARGET_FILE:pseudonl_BC> + -D PSEUDO_PURIFY=$<TARGET_FILE:pseudonl_purify> + -D PSEUDO_VALGRIND=$<TARGET_FILE:pseudonl_valgrind> + ${ARGN} + ) + set_tests_properties(CTestTestMemcheck${NAME} + PROPERTIES + PASS_REGULAR_EXPRESSION "\nCannot find memory tester output file: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/${NAME}/Testing/Temporary/MemoryChecker.1.log\n(.*\n)?Error in read script: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/${NAME}/test.cmake\n") +endfunction(gen_mcnl_test) + +unset(CTEST_EXTRA_CONFIG) +unset(CTEST_EXTRA_CODE) +unset(CMAKELISTS_EXTRA_CODE) + +gen_mc_test(DummyPurify "\${PSEUDO_PURIFY}") +gen_mc_test(DummyValgrind "\${PSEUDO_VALGRIND}") +gen_mc_test(DummyBC "\${PSEUDO_BC}") +gen_mcnl_test(DummyPurifyNoLogfile "\${PSEUDO_PURIFY}") +gen_mcnl_test(DummyValgrindNoLogfile "\${PSEUDO_VALGRIND}") +gen_mcnl_test(DummyBCNoLogfile "\${PSEUDO_BC}") + +set(CTEST_EXTRA_CODE "string(REPLACE \" \" \"\\\\ \" PRE_POST_COMMAND \"\${CTEST_MEMORYCHECK_COMMAND}\") + +set(CTEST_CUSTOM_PRE_MEMCHECK \"\${PRE_POST_COMMAND} pre command\") +set(CTEST_CUSTOM_POST_MEMCHECK \"\${PRE_POST_COMMAND} post command \") +") +gen_mc_test(DummyValgrindPrePost "\${PSEUDO_VALGRIND}") + +set(CTEST_EXTRA_CODE "set(CTEST_CUSTOM_POST_MEMCHECK \"\${ERROR_COMMAND}\")") +gen_mc_test(DummyValgrindFailPost "\${PSEUDO_VALGRIND}") + +set(CTEST_EXTRA_CODE "set(CTEST_CUSTOM_PRE_MEMCHECK \"\${ERROR_COMMAND}\")") +gen_mc_test(DummyValgrindFailPre "\${PSEUDO_VALGRIND}") + +unset(CTEST_EXTRA_CODE) +set(CTEST_EXTRA_CONFIG "set(CTEST_CUSTOM_MEMCHECK_IGNORE RunCMakeAgain)\n") +set(CMAKELISTS_EXTRA_CODE "add_test(NAME RunCMakeAgain COMMAND \"\${CMAKE_COMMAND}\" --version)") +gen_mc_test(DummyValgrindIgnoreMemcheck "\${PSEUDO_VALGRIND}") + +unset(CTEST_EXTRA_CONFIG) +gen_mc_test(DummyValgrindTwoTargets "\${PSEUDO_VALGRIND}" "-VV") + +set(CTEST_EXTRA_CONFIG "set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE \"\${CMAKE_CURRENT_BINARY_DIR}/does-not-exist\")") +unset(CMAKELISTS_EXTRA_CODE) +gen_mc_test(DummyValgrindInvalidSupFile "\${PSEUDO_VALGRIND}") + +# CTest will add the logfile option before any custom options. Set the logfile +# again, this time to an empty string. This will cause the logfile to be +# missing, which will be the prove for us that the custom option is indeed used. +set(CTEST_EXTRA_CONFIG "set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"--log-file=\")") +gen_mc_test(DummyValgrindCustomOptions "\${PSEUDO_VALGRIND}") + +unset(CTEST_EXTRA_CONFIG) +gen_mc_test(NotExist "\${CTEST_BINARY_DIRECTORY}/no-memcheck-exe") + +gen_mc_test(Unknown "${CMAKE_COMMAND}") string(REPLACE "\\" "\\\\" CMAKE_COMMAND_ESCAPED "${CMAKE_COMMAND}") string(REPLACE "(" "\\(" CMAKE_COMMAND_ESCAPED "${CMAKE_COMMAND_ESCAPED}") string(REPLACE ")" "\\)" CMAKE_COMMAND_ESCAPED "${CMAKE_COMMAND_ESCAPED}") string(REPLACE "+" "\\+" CMAKE_COMMAND_ESCAPED "${CMAKE_COMMAND_ESCAPED}") -foreach (_unkn Unknown UnknownQuoted) - set_tests_properties(CTestTestMemcheck${_unkn} PROPERTIES - PASS_REGULAR_EXPRESSION "Do not understand memory checker: ${CMAKE_COMMAND_ESCAPED}\n(.*\n)?Error in read script: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/${_unkn}/test.cmake\n") -endforeach () +set_tests_properties(CTestTestMemcheckUnknown PROPERTIES + PASS_REGULAR_EXPRESSION "Do not understand memory checker: ${CMAKE_COMMAND_ESCAPED}\n(.*\n)?Error in read script: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/Unknown/test.cmake\n") set_tests_properties(CTestTestMemcheckNotExist PROPERTIES PASS_REGULAR_EXPRESSION "Memory checker \\(MemoryCheckCommand\\) not set, or cannot find the specified program.") -set(NORMAL_CTEST_OUTPUT "\n-- Processing memory checking output: \nMemory checking results:\n(BullseyeCoverage[^\n]*\n)?") - # It is a valid result if valgrind does not output any files (can e.g. happen # if you have not compiled in debug mode), so these tests will not fail. -set_tests_properties(CTestTestMemcheckDummyValgrind CTestTestMemcheckDummyValgrindPrePost +set_tests_properties(CTestTestMemcheckDummyValgrind + CTestTestMemcheckDummyValgrindPrePost + CTestTestMemcheckDummyPurify PROPERTIES - PASS_REGULAR_EXPRESSION "${NORMAL_CTEST_OUTPUT}") + PASS_REGULAR_EXPRESSION "${NORMAL_CTEST_OUTPUT}${BULLSEYE_MSG}$") foreach (_pp Pre Post) string(TOLOWER ${_pp} _pp_lower) @@ -74,10 +157,17 @@ endforeach () set_tests_properties(CTestTestMemcheckDummyValgrindIgnoreMemcheck PROPERTIES - PASS_REGULAR_EXPRESSION "\n2/2 Test #2: RunCMakeAgain .*\n1/1 MemCheck #1: RunCMake .*${NORMAL_CTEST_OUTPUT}") - -set_tests_properties(CTestTestMemcheckDummyPurify PROPERTIES - PASS_REGULAR_EXPRESSION "\nCannot find memory tester output file: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyPurify/Testing/Temporary/MemoryChecker.log\n(.*\n)?Error in read script: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyPurify/test.cmake\n") + PASS_REGULAR_EXPRESSION "\n2/2 Test #2: RunCMakeAgain .*${NORMAL_CTEST_OUTPUT}${BULLSEYE_MSG}$") set_tests_properties(CTestTestMemcheckDummyBC PROPERTIES - PASS_REGULAR_EXPRESSION "\nCannot find memory tester output file: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyBC/Testing/Temporary/MemoryChecker.log\n(.*\n)?Error parsing XML in stream at line 1: no element found\n(.*\n)?Error in read script: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyBC/test.cmake\n") + PASS_REGULAR_EXPRESSION "\n1/1 MemCheck #1: RunCMake \\.+ Passed +[0-9]+.[0-9]+ sec\n\n100% tests passed, 0 tests failed out of 1\n(.*\n)?Error parsing XML in stream at line 1: no element found\n") + +set_tests_properties(CTestTestMemcheckDummyValgrindInvalidSupFile PROPERTIES + PASS_REGULAR_EXPRESSION "\nCannot find memory checker suppression file: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/does-not-exist\n") + +set_tests_properties(CTestTestMemcheckDummyValgrindCustomOptions PROPERTIES + PASS_REGULAR_EXPRESSION "\nCannot find memory tester output file: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindCustomOptions/Testing/Temporary/MemoryChecker.1.log\n(.*\n)?Error in read script: ${CMAKE_CURRENT_BINARY_DIR}/DummyValgrindCustomOptions/test.cmake\n") + +set_tests_properties(CTestTestMemcheckDummyValgrindTwoTargets PROPERTIES + PASS_REGULAR_EXPRESSION + "\nMemory check project ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets\n.*\n *Start 1: RunCMake\n(.*\n)?Memory check command: .* \"--log-file=${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets/Testing/Temporary/MemoryChecker.1.log\" \"-q\".*\n *Start 2: RunCMakeAgain\n(.*\n)?Memory check command: .* \"--log-file=${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets/Testing/Temporary/MemoryChecker.2.log\" \"-q\".*\n") diff --git a/Tests/CTestTestMemcheck/CMakeLists.txt.in b/Tests/CTestTestMemcheck/CMakeLists.txt.in new file mode 100644 index 000000000..e28e56a9a --- /dev/null +++ b/Tests/CTestTestMemcheck/CMakeLists.txt.in @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.8.9) +project(CTestTestMemcheck@SUBTEST_NAME@) +include(CTest) + +add_test(NAME RunCMake COMMAND "${CMAKE_COMMAND}" --version) + +@CMAKELISTS_EXTRA_CODE@ diff --git a/Tests/CTestTestMemcheck/DummyValgrindPrePost/CTestConfig.cmake b/Tests/CTestTestMemcheck/CTestConfig.cmake.in index 6e4c2e86c..6cf37828f 100644 --- a/Tests/CTestTestMemcheck/DummyValgrindPrePost/CTestConfig.cmake +++ b/Tests/CTestTestMemcheck/CTestConfig.cmake.in @@ -1,7 +1,9 @@ -set (CTEST_PROJECT_NAME "CTestTestMemcheckDummyValgrindPrePost") +set (CTEST_PROJECT_NAME "CTestTestMemcheck@SUBTEST_NAME@") set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") set (CTEST_DART_SERVER_VERSION "2") set(CTEST_DROP_METHOD "http") set(CTEST_DROP_SITE "www.cdash.org") set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") set(CTEST_DROP_SITE_CDASH TRUE) + +@CTEST_EXTRA_CONFIG@ diff --git a/Tests/CTestTestMemcheck/DummyBC/CMakeLists.txt b/Tests/CTestTestMemcheck/DummyBC/CMakeLists.txt deleted file mode 100644 index aa0e495da..000000000 --- a/Tests/CTestTestMemcheck/DummyBC/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) -project(CTestTestMemcheckDummyBC) -include(CTest) - -add_test (RunCMake "${CMAKE_COMMAND}") diff --git a/Tests/CTestTestMemcheck/DummyBC/CTestConfig.cmake b/Tests/CTestTestMemcheck/DummyBC/CTestConfig.cmake deleted file mode 100644 index 39cdd88cc..000000000 --- a/Tests/CTestTestMemcheck/DummyBC/CTestConfig.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set (CTEST_PROJECT_NAME "CTestTestMemcheckDummyBC") -set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -set (CTEST_DART_SERVER_VERSION "2") -set(CTEST_DROP_METHOD "http") -set(CTEST_DROP_SITE "www.cdash.org") -set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") -set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestMemcheck/DummyPurify/CMakeLists.txt b/Tests/CTestTestMemcheck/DummyPurify/CMakeLists.txt deleted file mode 100644 index dfd93fde4..000000000 --- a/Tests/CTestTestMemcheck/DummyPurify/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) -project(CTestTestMemcheckDummyPurify) -include(CTest) - -add_test (RunCMake "${CMAKE_COMMAND}") diff --git a/Tests/CTestTestMemcheck/DummyPurify/CTestConfig.cmake b/Tests/CTestTestMemcheck/DummyPurify/CTestConfig.cmake deleted file mode 100644 index 40b960867..000000000 --- a/Tests/CTestTestMemcheck/DummyPurify/CTestConfig.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set (CTEST_PROJECT_NAME "CTestTestMemcheckDummyPurify") -set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -set (CTEST_DART_SERVER_VERSION "2") -set(CTEST_DROP_METHOD "http") -set(CTEST_DROP_SITE "www.cdash.org") -set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") -set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestMemcheck/DummyPurify/test.cmake.in b/Tests/CTestTestMemcheck/DummyPurify/test.cmake.in deleted file mode 100644 index 0c8795cf5..000000000 --- a/Tests/CTestTestMemcheck/DummyPurify/test.cmake.in +++ /dev/null @@ -1,25 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) - -# Settings: -set(CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@") -set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-MemcheckDummyPurify") - -set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_SOURCE_DIR@/DummyPurify") -set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/DummyPurify") -set(CTEST_CVS_COMMAND "@CVSCOMMAND@") -set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") -set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") -set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") -set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") - -set(CTEST_MEMORYCHECK_COMMAND "${PSEUDO_PURIFY}") - -#CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY}) - -CTEST_START(Experimental) -CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -#CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) diff --git a/Tests/CTestTestMemcheck/DummyValgrind/CMakeLists.txt b/Tests/CTestTestMemcheck/DummyValgrind/CMakeLists.txt deleted file mode 100644 index 822966ade..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrind/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) -project(CTestTestMemcheckDummyValgrind) -include(CTest) - -add_test (RunCMake "${CMAKE_COMMAND}") diff --git a/Tests/CTestTestMemcheck/DummyValgrind/CTestConfig.cmake b/Tests/CTestTestMemcheck/DummyValgrind/CTestConfig.cmake deleted file mode 100644 index 4ca59a42e..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrind/CTestConfig.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set (CTEST_PROJECT_NAME "CTestTestMemcheckDummyValgrind") -set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -set (CTEST_DART_SERVER_VERSION "2") -set(CTEST_DROP_METHOD "http") -set(CTEST_DROP_SITE "www.cdash.org") -set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") -set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestMemcheck/DummyValgrind/test.cmake.in b/Tests/CTestTestMemcheck/DummyValgrind/test.cmake.in deleted file mode 100644 index c3941c1f9..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrind/test.cmake.in +++ /dev/null @@ -1,25 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) - -# Settings: -set(CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@") -set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-MemcheckDummyValgrind") - -set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_SOURCE_DIR@/DummyValgrind") -set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/DummyValgrind") -set(CTEST_CVS_COMMAND "@CVSCOMMAND@") -set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") -set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") -set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") -set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") - -set(CTEST_MEMORYCHECK_COMMAND "${PSEUDO_VALGRIND}") - -#CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY}) - -CTEST_START(Experimental) -CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -#CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) diff --git a/Tests/CTestTestMemcheck/DummyValgrindFailPost/CMakeLists.txt b/Tests/CTestTestMemcheck/DummyValgrindFailPost/CMakeLists.txt deleted file mode 100644 index 8185071af..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindFailPost/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) -project(CTestTestMemcheckDummyValgrindFailPost) -include(CTest) - -add_test (RunCMake "${CMAKE_COMMAND}") diff --git a/Tests/CTestTestMemcheck/DummyValgrindFailPost/CTestConfig.cmake b/Tests/CTestTestMemcheck/DummyValgrindFailPost/CTestConfig.cmake deleted file mode 100644 index 4ca59a42e..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindFailPost/CTestConfig.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set (CTEST_PROJECT_NAME "CTestTestMemcheckDummyValgrind") -set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -set (CTEST_DART_SERVER_VERSION "2") -set(CTEST_DROP_METHOD "http") -set(CTEST_DROP_SITE "www.cdash.org") -set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") -set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestMemcheck/DummyValgrindFailPost/test.cmake.in b/Tests/CTestTestMemcheck/DummyValgrindFailPost/test.cmake.in deleted file mode 100644 index 90e2ac528..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindFailPost/test.cmake.in +++ /dev/null @@ -1,27 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) - -# Settings: -set(CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@") -set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-MemcheckDummyValgrindFailPost") - -set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_SOURCE_DIR@/DummyValgrindFailPost") -set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/DummyValgrindFailPost") -set(CTEST_CVS_COMMAND "@CVSCOMMAND@") -set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") -set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") -set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") -set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") - -set(CTEST_MEMORYCHECK_COMMAND "${PSEUDO_VALGRIND}") - -set(CTEST_CUSTOM_POST_MEMCHECK "${ERROR_COMMAND}") - -#CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY}) - -CTEST_START(Experimental) -CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -#CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) diff --git a/Tests/CTestTestMemcheck/DummyValgrindFailPre/CMakeLists.txt b/Tests/CTestTestMemcheck/DummyValgrindFailPre/CMakeLists.txt deleted file mode 100644 index 3714cd6a3..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindFailPre/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) -project(CTestTestMemcheckDummyValgrindFailPre) -include(CTest) - -add_test (RunCMake "${CMAKE_COMMAND}") diff --git a/Tests/CTestTestMemcheck/DummyValgrindFailPre/CTestConfig.cmake b/Tests/CTestTestMemcheck/DummyValgrindFailPre/CTestConfig.cmake deleted file mode 100644 index 4ca59a42e..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindFailPre/CTestConfig.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set (CTEST_PROJECT_NAME "CTestTestMemcheckDummyValgrind") -set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -set (CTEST_DART_SERVER_VERSION "2") -set(CTEST_DROP_METHOD "http") -set(CTEST_DROP_SITE "www.cdash.org") -set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") -set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestMemcheck/DummyValgrindFailPre/test.cmake.in b/Tests/CTestTestMemcheck/DummyValgrindFailPre/test.cmake.in deleted file mode 100644 index fd17f638b..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindFailPre/test.cmake.in +++ /dev/null @@ -1,27 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) - -# Settings: -set(CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@") -set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-MemcheckDummyValgrindFailPre") - -set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_SOURCE_DIR@/DummyValgrindFailPre") -set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/DummyValgrindFailPre") -set(CTEST_CVS_COMMAND "@CVSCOMMAND@") -set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") -set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") -set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") -set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") - -set(CTEST_MEMORYCHECK_COMMAND "${PSEUDO_VALGRIND}") - -set(CTEST_CUSTOM_PRE_MEMCHECK "${ERROR_COMMAND}") - -#CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY}) - -CTEST_START(Experimental) -CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -#CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) diff --git a/Tests/CTestTestMemcheck/DummyValgrindIgnoreMemcheck/CMakeLists.txt b/Tests/CTestTestMemcheck/DummyValgrindIgnoreMemcheck/CMakeLists.txt deleted file mode 100644 index 5d437d1b7..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindIgnoreMemcheck/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) -project(CTestTestMemcheckDummyValgrindIgnoreMemcheck) -include(CTest) - -add_test (RunCMake "${CMAKE_COMMAND}") -add_test (RunCMakeAgain "${CMAKE_COMMAND}") diff --git a/Tests/CTestTestMemcheck/DummyValgrindIgnoreMemcheck/CTestConfig.cmake b/Tests/CTestTestMemcheck/DummyValgrindIgnoreMemcheck/CTestConfig.cmake deleted file mode 100644 index 6eee3e602..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindIgnoreMemcheck/CTestConfig.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set (CTEST_PROJECT_NAME "CTestTestMemcheckDummyValgrindIgnoreMemcheck") -set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -set (CTEST_DART_SERVER_VERSION "2") -set(CTEST_DROP_METHOD "http") -set(CTEST_DROP_SITE "www.cdash.org") -set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") -set(CTEST_DROP_SITE_CDASH TRUE) - -set(CTEST_CUSTOM_MEMCHECK_IGNORE RunCMakeAgain) diff --git a/Tests/CTestTestMemcheck/DummyValgrindIgnoreMemcheck/test.cmake.in b/Tests/CTestTestMemcheck/DummyValgrindIgnoreMemcheck/test.cmake.in deleted file mode 100644 index 37aaaeb26..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindIgnoreMemcheck/test.cmake.in +++ /dev/null @@ -1,25 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) - -# Settings: -set(CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@") -set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-MemcheckDummyValgrindIgnoreMemcheck") - -set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_SOURCE_DIR@/DummyValgrindIgnoreMemcheck") -set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/DummyValgrindIgnoreMemcheck") -set(CTEST_CVS_COMMAND "@CVSCOMMAND@") -set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") -set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") -set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") -set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") - -set(CTEST_MEMORYCHECK_COMMAND "${PSEUDO_VALGRIND}") - -#CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY}) - -CTEST_START(Experimental) -CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -#CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) diff --git a/Tests/CTestTestMemcheck/DummyValgrindPrePost/CMakeLists.txt b/Tests/CTestTestMemcheck/DummyValgrindPrePost/CMakeLists.txt deleted file mode 100644 index bc1563212..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindPrePost/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) -project(CTestTestMemcheckDummyValgrindPrePost) -include(CTest) - -add_test (RunCMake "${CMAKE_COMMAND}") diff --git a/Tests/CTestTestMemcheck/DummyValgrindPrePost/test.cmake.in b/Tests/CTestTestMemcheck/DummyValgrindPrePost/test.cmake.in deleted file mode 100644 index 11f14a950..000000000 --- a/Tests/CTestTestMemcheck/DummyValgrindPrePost/test.cmake.in +++ /dev/null @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) - -# Settings: -set(CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@") -set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-MemcheckDummyValgrindPrePost") - -set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_SOURCE_DIR@/DummyValgrindPrePost") -set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/DummyValgrindPrePost") -set(CTEST_CVS_COMMAND "@CVSCOMMAND@") -set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") -set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") -set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") -set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") - -set(CTEST_MEMORYCHECK_COMMAND "${PSEUDO_VALGRIND}") - -set(CTEST_CUSTOM_PRE_MEMCHECK "${CTEST_MEMORYCHECK_COMMAND}") -set(CTEST_CUSTOM_POST_MEMCHECK "${CTEST_MEMORYCHECK_COMMAND}") - -#CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY}) - -CTEST_START(Experimental) -CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -#CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) diff --git a/Tests/CTestTestMemcheck/NoLogDummyChecker/CMakeLists.txt b/Tests/CTestTestMemcheck/NoLogDummyChecker/CMakeLists.txt new file mode 100644 index 000000000..c5aa2cdbd --- /dev/null +++ b/Tests/CTestTestMemcheck/NoLogDummyChecker/CMakeLists.txt @@ -0,0 +1,17 @@ +# A dummy checker implementation that does not write the requested output file +# so it triggers an error for every checker. + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ret0.c" "int main(){return 0;}\n") + +foreach(_pseudo IN ITEMS valgrind purify BC) + add_executable(pseudonl_${_pseudo} "${CMAKE_CURRENT_BINARY_DIR}/ret0.c") + set_target_properties(pseudonl_${_pseudo} PROPERTIES OUTPUT_NAME ${_pseudo}) +endforeach() + +# Xcode 2.x forgets to create the output directory before linking +# the individual architectures. +if(CMAKE_OSX_ARCHITECTURES AND XCODE AND NOT "${XCODE_VERSION}" MATCHES "^[^12]") + add_custom_command(TARGET pseudonl_valgrind + PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}" + ) +endif() diff --git a/Tests/CTestTestMemcheck/NotExist/CMakeLists.txt b/Tests/CTestTestMemcheck/NotExist/CMakeLists.txt deleted file mode 100644 index 4d905de9e..000000000 --- a/Tests/CTestTestMemcheck/NotExist/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) -project(CTestTestMemcheckNotExist) -include(CTest) - -add_test (RunCMake "${CMAKE_COMMAND}") diff --git a/Tests/CTestTestMemcheck/NotExist/CTestConfig.cmake b/Tests/CTestTestMemcheck/NotExist/CTestConfig.cmake deleted file mode 100644 index 3ed84aab9..000000000 --- a/Tests/CTestTestMemcheck/NotExist/CTestConfig.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set (CTEST_PROJECT_NAME "CTestTestMemcheckUnknown") -set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -set (CTEST_DART_SERVER_VERSION "2") -set(CTEST_DROP_METHOD "http") -set(CTEST_DROP_SITE "www.cdash.org") -set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") -set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestMemcheck/NotExist/test.cmake.in b/Tests/CTestTestMemcheck/NotExist/test.cmake.in deleted file mode 100644 index 43f754272..000000000 --- a/Tests/CTestTestMemcheck/NotExist/test.cmake.in +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) - -# Settings: -set(CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@") -set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-MemcheckNotExist") - -set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_SOURCE_DIR@/NotExist") -set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/NotExist") -set(CTEST_CVS_COMMAND "@CVSCOMMAND@") -set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") -set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") -set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") -set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") -set(CTEST_MEMORYCHECK_COMMAND "${CTEST_BINARY_DIRECTORY}/no-memcheck-exe") - -CTEST_START(Experimental) -CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) diff --git a/Tests/CTestTestMemcheck/Unknown/CMakeLists.txt b/Tests/CTestTestMemcheck/Unknown/CMakeLists.txt deleted file mode 100644 index 3fd3103ba..000000000 --- a/Tests/CTestTestMemcheck/Unknown/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) -project(CTestTestMemcheckUnknown) -include(CTest) - -add_test (RunCMake "${CMAKE_COMMAND}") diff --git a/Tests/CTestTestMemcheck/Unknown/CTestConfig.cmake b/Tests/CTestTestMemcheck/Unknown/CTestConfig.cmake deleted file mode 100644 index 3ed84aab9..000000000 --- a/Tests/CTestTestMemcheck/Unknown/CTestConfig.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set (CTEST_PROJECT_NAME "CTestTestMemcheckUnknown") -set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -set (CTEST_DART_SERVER_VERSION "2") -set(CTEST_DROP_METHOD "http") -set(CTEST_DROP_SITE "www.cdash.org") -set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") -set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestMemcheck/Unknown/test.cmake.in b/Tests/CTestTestMemcheck/Unknown/test.cmake.in deleted file mode 100644 index 0830bf056..000000000 --- a/Tests/CTestTestMemcheck/Unknown/test.cmake.in +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) - -# Settings: -set(CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@") -set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-MemcheckUnknown") - -set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_SOURCE_DIR@/Unknown") -set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/Unknown") -set(CTEST_CVS_COMMAND "@CVSCOMMAND@") -set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") -set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") -set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") -set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") -set(CTEST_MEMORYCHECK_COMMAND "@CMAKE_COMMAND@") - -CTEST_START(Experimental) -CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) diff --git a/Tests/CTestTestMemcheck/UnknownQuoted/CMakeLists.txt b/Tests/CTestTestMemcheck/UnknownQuoted/CMakeLists.txt deleted file mode 100644 index 6f49c6144..000000000 --- a/Tests/CTestTestMemcheck/UnknownQuoted/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) -project(CTestTestMemcheckUnknownQuoted) -include(CTest) - -add_test (RunCMake "\"${CMAKE_COMMAND}\"") diff --git a/Tests/CTestTestMemcheck/UnknownQuoted/CTestConfig.cmake b/Tests/CTestTestMemcheck/UnknownQuoted/CTestConfig.cmake deleted file mode 100644 index f0233a7a4..000000000 --- a/Tests/CTestTestMemcheck/UnknownQuoted/CTestConfig.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set (CTEST_PROJECT_NAME "CTestTestMemcheckUnknownQuoted") -set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") -set (CTEST_DART_SERVER_VERSION "2") -set(CTEST_DROP_METHOD "http") -set(CTEST_DROP_SITE "www.cdash.org") -set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") -set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestMemcheck/UnknownQuoted/test.cmake.in b/Tests/CTestTestMemcheck/UnknownQuoted/test.cmake.in deleted file mode 100644 index 1b1f7023a..000000000 --- a/Tests/CTestTestMemcheck/UnknownQuoted/test.cmake.in +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 2.8.9) - -# Settings: -set(CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@") -set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-MemcheckUnknownQuoted") - -set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_SOURCE_DIR@/UnknownQuoted") -set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/UnknownQuoted") -set(CTEST_CVS_COMMAND "@CVSCOMMAND@") -set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") -set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") -set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") -set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") -set(CTEST_MEMORYCHECK_COMMAND "@CMAKE_COMMAND@") - -CTEST_START(Experimental) -CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) diff --git a/Tests/CTestTestMemcheck/memtester.cxx.in b/Tests/CTestTestMemcheck/memtester.cxx.in new file mode 100644 index 000000000..55a34e34f --- /dev/null +++ b/Tests/CTestTestMemcheck/memtester.cxx.in @@ -0,0 +1,52 @@ +#include <cmSystemTools.h> +#include <string> + +#define RETVAL @_retval@ + +int +main(int argc, char **argv) +{ + std::string exename = argv[0]; + std::string logarg; + bool nextarg = false; + + if (exename.find("valgrind") != exename.npos) + logarg = "--log-file="; + else if (exename.find("purify") != exename.npos) +#ifdef _WIN32 + logarg = "/SAVETEXTDATA="; +#else + logarg = "-log-file="; +#endif + else if (exename.find("BC") != exename.npos) + { + nextarg = true; + logarg = "/X"; + } + + if (!logarg.empty()) { + std::string logfile; + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + if (arg.find(logarg) == 0) + { + if (nextarg) + { + if (i == argc - 1) + return 1; // invalid command line + logfile = argv[i + 1]; + } + else + { + logfile = arg.substr(logarg.length()); + } + // keep searching, it may be overridden later to provoke an error + } + } + + if (!logfile.empty()) + cmSystemTools::Touch(logfile.c_str(), true); + } + + return RETVAL; +} diff --git a/Tests/CTestTestMemcheck/DummyBC/test.cmake.in b/Tests/CTestTestMemcheck/test.cmake.in index 1b16433fb..6c388c52c 100644 --- a/Tests/CTestTestMemcheck/DummyBC/test.cmake.in +++ b/Tests/CTestTestMemcheck/test.cmake.in @@ -3,10 +3,10 @@ cmake_minimum_required(VERSION 2.8.9) # Settings: set(CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@") set(CTEST_SITE "@SITE@") -set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-MemcheckDummyBC") +set(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-Memcheck@SUBTEST_NAME@") -set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_SOURCE_DIR@/DummyBC") -set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/DummyBC") +set(CTEST_SOURCE_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/@SUBTEST_NAME@") +set(CTEST_BINARY_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/@SUBTEST_NAME@") set(CTEST_CVS_COMMAND "@CVSCOMMAND@") set(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@") set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_TEST_GENERATOR_TOOLSET@") @@ -14,12 +14,11 @@ set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") set(CTEST_COVERAGE_COMMAND "@COVERAGE_COMMAND@") set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") -set(CTEST_MEMORYCHECK_COMMAND "${PSEUDO_BC}") +set(CTEST_MEMORYCHECK_COMMAND "@CHECKER_COMMAND@") -#CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY}) +@CTEST_EXTRA_CODE@ CTEST_START(Experimental) CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) -#CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) diff --git a/Tests/CompatibleInterface/CMakeLists.txt b/Tests/CompatibleInterface/CMakeLists.txt index cd0a37d20..ae1d2fa43 100644 --- a/Tests/CompatibleInterface/CMakeLists.txt +++ b/Tests/CompatibleInterface/CMakeLists.txt @@ -57,10 +57,10 @@ set_property(TARGET iface2 APPEND PROPERTY # properties defined only in the interface - they should be implicitly zero set_property(TARGET iface2 APPEND PROPERTY - LINK_INTERFACE_LIBRARIES $<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP4>>:nonexistant> + LINK_INTERFACE_LIBRARIES $<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP4>>:nonexistent> ) target_link_libraries(CompatibleInterface iface2 - $<$<BOOL:$<TARGET_PROPERTY:Iface2_PROP>>:nonexistant> + $<$<BOOL:$<TARGET_PROPERTY:Iface2_PROP>>:nonexistent> ) # Test that this does not segfault: target_compile_definitions(CompatibleInterface @@ -70,7 +70,7 @@ target_compile_definitions(CompatibleInterface # The COMPATIBLE_INTERFACE_* properties are only read from dependencies # in the interface. Populating it on the CompatibleInterface target does -# not have any affect on the interpretation of the INTERFACE variants +# not have any effect on the interpretation of the INTERFACE variants # in dependencies. set_property(TARGET iface1 PROPERTY INTERFACE_NON_RELEVANT_PROP ON diff --git a/Tests/CompileDefinitions/CMakeLists.txt b/Tests/CompileDefinitions/CMakeLists.txt index d3e9a3eae..930d22058 100644 --- a/Tests/CompileDefinitions/CMakeLists.txt +++ b/Tests/CompileDefinitions/CMakeLists.txt @@ -5,6 +5,7 @@ project(CompileDefinitions) if ("${CMAKE_GENERATOR}" STREQUAL "Visual Studio 6") add_definitions(-DNO_SPACES_IN_DEFINE_VALUES) + set(NO_SPACES_IN_DEFINE_VALUES 1) endif() # Use compile flags to tell executables which config is built diff --git a/Tests/CompileDefinitions/add_definitions_command/CMakeLists.txt b/Tests/CompileDefinitions/add_definitions_command/CMakeLists.txt index d3886a104..23e013425 100644 --- a/Tests/CompileDefinitions/add_definitions_command/CMakeLists.txt +++ b/Tests/CompileDefinitions/add_definitions_command/CMakeLists.txt @@ -1,8 +1,15 @@ project(add_definitions_command) -add_definitions(-DCMAKE_IS_FUN -DCMAKE_IS=Fun -DCMAKE_IS_="Fun" -DCMAKE_IS_REALLY="Very Fun") -add_definitions(-DCMAKE_IS_="Fun" -DCMAKE_IS_REALLY="Very Fun" -DCMAKE_IS_FUN -DCMAKE_IS=Fun) +add_definitions(-DCMAKE_IS_FUN -DCMAKE_IS=Fun -DCMAKE_IS_="Fun") +if (NOT NO_SPACES_IN_DEFINE_VALUES) + add_definitions(-DCMAKE_IS_REALLY="Very Fun") +endif() +add_definitions(-DCMAKE_IS_="Fun") +if (NOT NO_SPACES_IN_DEFINE_VALUES) + add_definitions(-DCMAKE_IS_REALLY="Very Fun") +endif() +add_definitions(-DCMAKE_IS_FUN -DCMAKE_IS=Fun) add_definitions(-DBUILD_IS_DEBUG=$<CONFIG:Debug> -DBUILD_IS_NOT_DEBUG=$<NOT:$<CONFIG:Debug>>) add_executable(add_definitions_command_executable ../compiletest.cpp) diff --git a/Tests/CompileDefinitions/add_definitions_command_with_target_prop/CMakeLists.txt b/Tests/CompileDefinitions/add_definitions_command_with_target_prop/CMakeLists.txt index 5587f7f99..55108db7a 100644 --- a/Tests/CompileDefinitions/add_definitions_command_with_target_prop/CMakeLists.txt +++ b/Tests/CompileDefinitions/add_definitions_command_with_target_prop/CMakeLists.txt @@ -7,7 +7,9 @@ add_executable(add_definitions_command_with_target_prop_executable ../compiletes set_target_properties(add_definitions_command_with_target_prop_executable PROPERTIES COMPILE_DEFINITIONS CMAKE_IS_="Fun") -set_property(TARGET add_definitions_command_with_target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_REALLY="Very Fun") +if (NOT NO_SPACES_IN_DEFINE_VALUES) + set_property(TARGET add_definitions_command_with_target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_REALLY="Very Fun") +endif() add_definitions(-DCMAKE_IS_FUN) diff --git a/Tests/CompileDefinitions/compiletest.c b/Tests/CompileDefinitions/compiletest.c new file mode 100644 index 000000000..d7883af77 --- /dev/null +++ b/Tests/CompileDefinitions/compiletest.c @@ -0,0 +1,19 @@ + +#ifndef LINK_C_DEFINE +#error Expected LINK_C_DEFINE +#endif +#ifndef LINK_LANGUAGE_IS_C +#error Expected LINK_LANGUAGE_IS_C +#endif + +#ifdef LINK_CXX_DEFINE +#error Unexpected LINK_CXX_DEFINE +#endif +#ifdef LINK_LANGUAGE_IS_CXX +#error Unexpected LINK_LANGUAGE_IS_CXX +#endif + +int main(void) +{ + return 0; +} diff --git a/Tests/CompileDefinitions/compiletest.cpp b/Tests/CompileDefinitions/compiletest.cpp index 14b8eab4a..7df09df81 100644 --- a/Tests/CompileDefinitions/compiletest.cpp +++ b/Tests/CompileDefinitions/compiletest.cpp @@ -20,10 +20,16 @@ static const char very_fun_string[] = CMAKE_IS_REALLY; #endif enum { - StringLiteralTest1 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_) == sizeof("Fun")>) + StringLiteralTest1 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_) == sizeof("Fun")>), #ifndef NO_SPACES_IN_DEFINE_VALUES - , - StringLiteralTest2 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_REALLY) == sizeof("Very Fun")>) + StringLiteralTest2 = sizeof(CMakeStaticAssert<sizeof(CMAKE_IS_REALLY) == sizeof("Very Fun")>), +#endif +#ifdef TEST_GENERATOR_EXPRESSIONS + StringLiteralTest3 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST1) == sizeof("A,B,C,D")>), + StringLiteralTest4 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST2) == sizeof("A,,B,,C,,D")>), + StringLiteralTest5 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST3) == sizeof("A,-B,-C,-D")>), + StringLiteralTest6 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST4) == sizeof("A-,-B-,-C-,-D")>), + StringLiteralTest7 = sizeof(CMakeStaticAssert<sizeof(LETTER_LIST5) == sizeof("A-,B-,C-,D")>) #endif }; @@ -42,6 +48,29 @@ enum { #error Expected define expanded from list #endif +#ifndef PREFIX_DEF1 +#error Expect PREFIX_DEF1 +#endif + +#ifndef PREFIX_DEF2 +#error Expect PREFIX_DEF2 +#endif + +#ifndef LINK_CXX_DEFINE +#error Expected LINK_CXX_DEFINE +#endif +#ifndef LINK_LANGUAGE_IS_CXX +#error Expected LINK_LANGUAGE_IS_CXX +#endif + +#ifdef LINK_C_DEFINE +#error Unexpected LINK_C_DEFINE +#endif +#ifdef LINK_LANGUAGE_IS_C +#error Unexpected LINK_LANGUAGE_IS_C +#endif + + // TEST_GENERATOR_EXPRESSIONS #endif diff --git a/Tests/CompileDefinitions/compiletest_mixed_c.c b/Tests/CompileDefinitions/compiletest_mixed_c.c new file mode 100644 index 000000000..a270b2b12 --- /dev/null +++ b/Tests/CompileDefinitions/compiletest_mixed_c.c @@ -0,0 +1,23 @@ + +#ifndef LINK_CXX_DEFINE +#error Expected LINK_CXX_DEFINE +#endif +#ifndef LINK_LANGUAGE_IS_CXX +#error Expected LINK_LANGUAGE_IS_CXX +#endif + +#ifdef LINK_C_DEFINE +#error Unexpected LINK_C_DEFINE +#endif +#ifdef LINK_LANGUAGE_IS_C +#error Unexpected LINK_LANGUAGE_IS_C +#endif + +#ifndef C_EXECUTABLE_LINK_LANGUAGE_IS_C +#error Expected C_EXECUTABLE_LINK_LANGUAGE_IS_C define +#endif + +void someFunc(void) +{ + +} diff --git a/Tests/CompileDefinitions/compiletest_mixed_cxx.cpp b/Tests/CompileDefinitions/compiletest_mixed_cxx.cpp new file mode 100644 index 000000000..ae6befc5f --- /dev/null +++ b/Tests/CompileDefinitions/compiletest_mixed_cxx.cpp @@ -0,0 +1,23 @@ + +#ifndef LINK_CXX_DEFINE +#error Expected LINK_CXX_DEFINE +#endif +#ifndef LINK_LANGUAGE_IS_CXX +#error Expected LINK_LANGUAGE_IS_CXX +#endif + +#ifdef LINK_C_DEFINE +#error Unexpected LINK_C_DEFINE +#endif +#ifdef LINK_LANGUAGE_IS_C +#error Unexpected LINK_LANGUAGE_IS_C +#endif + +#ifndef C_EXECUTABLE_LINK_LANGUAGE_IS_C +#error Expected C_EXECUTABLE_LINK_LANGUAGE_IS_C define +#endif + +int main(int argc, char **argv) +{ + return 0; +} diff --git a/Tests/CompileDefinitions/target_prop/CMakeLists.txt b/Tests/CompileDefinitions/target_prop/CMakeLists.txt index 1ef2d6d6e..a0d3f4e96 100644 --- a/Tests/CompileDefinitions/target_prop/CMakeLists.txt +++ b/Tests/CompileDefinitions/target_prop/CMakeLists.txt @@ -5,7 +5,11 @@ add_executable(target_prop_executable ../compiletest.cpp) set_target_properties(target_prop_executable PROPERTIES COMPILE_DEFINITIONS CMAKE_IS_FUN) -set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_REALLY="Very Fun" CMAKE_IS=Fun) +if (NOT NO_SPACES_IN_DEFINE_VALUES) + set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_REALLY="Very Fun" CMAKE_IS=Fun) +else() + set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS=Fun) +endif() set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_FUN CMAKE_IS_="Fun") set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS @@ -13,9 +17,36 @@ set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS "$<1:CMAKE_IS_DECLARATIVE>" "$<0:GE_NOT_DEFINED>" "$<1:ARGUMENT;LIST>" + PREFIX_$<JOIN:DEF1;DEF2,;PREFIX_> + LETTER_LIST1=\"$<JOIN:A;B;C;D,,>\" + LETTER_LIST2=\"$<JOIN:A;B;C;D,,,>\" + LETTER_LIST3=\"$<JOIN:A;B;C;D,,->\" + LETTER_LIST4=\"$<JOIN:A;B;C;D,-,->\" + LETTER_LIST5=\"$<JOIN:A;B;C;D,-,>\" + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:LINK_CXX_DEFINE>" + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>:LINK_C_DEFINE>" + "LINK_LANGUAGE_IS_$<TARGET_PROPERTY:LINKER_LANGUAGE>" ) set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS BUILD_IS_DEBUG=$<CONFIG:Debug> BUILD_IS_NOT_DEBUG=$<NOT:$<CONFIG:Debug>> ) + +add_executable(target_prop_c_executable ../compiletest.c) + +set_property(TARGET target_prop_c_executable APPEND PROPERTY COMPILE_DEFINITIONS + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:LINK_CXX_DEFINE>" + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>:LINK_C_DEFINE>" + "LINK_LANGUAGE_IS_$<TARGET_PROPERTY:LINKER_LANGUAGE>" + ) + +# Resulting link language will be CXX +add_executable(target_prop_mixed_executable ../compiletest_mixed_c.c ../compiletest_mixed_cxx.cpp) + +set_property(TARGET target_prop_mixed_executable APPEND PROPERTY COMPILE_DEFINITIONS + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:LINK_CXX_DEFINE>" + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>:LINK_C_DEFINE>" + "LINK_LANGUAGE_IS_$<TARGET_PROPERTY:LINKER_LANGUAGE>" + "C_EXECUTABLE_LINK_LANGUAGE_IS_$<TARGET_PROPERTY:target_prop_c_executable,LINKER_LANGUAGE>" + ) diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt new file mode 100644 index 000000000..9b6c9c2a0 --- /dev/null +++ b/Tests/CompileOptions/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required(VERSION 2.8) + +project(CompileOptions) + +add_library(testlib other.cpp) + +add_executable(CompileOptions main.cpp) + +macro(get_compiler_test_genex lst lang) + list(APPEND ${lst} -DTEST_${lang}_COMPILER_VERSION="$<${lang}_COMPILER_VERSION>") + list(APPEND ${lst} -DTEST_${lang}_COMPILER_VERSION_EQUALITY=$<${lang}_COMPILER_VERSION:${CMAKE_${lang}_COMPILER_VERSION}>) +endmacro() + +get_compiler_test_genex(c_tests C) +get_compiler_test_genex(cxx_tests CXX) + +set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS + "-DTEST_DEFINE" + "-DNEEDS_ESCAPE=\"E$CAPE\"" + "$<$<CXX_COMPILER_ID:GNU>:-DTEST_DEFINE_GNU>" + ${c_tests} + ${cxx_tests} + ) + +target_link_libraries(CompileOptions testlib) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(CompileOptions + PRIVATE + "DO_GNU_TESTS" + ) +endif() + +target_compile_definitions(CompileOptions + PRIVATE + "EXPECTED_C_COMPILER_VERSION=\"${CMAKE_C_COMPILER_VERSION}\"" + "EXPECTED_CXX_COMPILER_VERSION=\"${CMAKE_CXX_COMPILER_VERSION}\"" +) diff --git a/Tests/CompileOptions/main.cpp b/Tests/CompileOptions/main.cpp new file mode 100644 index 000000000..42f4cca11 --- /dev/null +++ b/Tests/CompileOptions/main.cpp @@ -0,0 +1,24 @@ +#ifndef TEST_DEFINE +# error Expected definition TEST_DEFINE +#endif + +#ifndef NEEDS_ESCAPE +# error Expected definition NEEDS_ESCAPE +#endif + +#ifdef DO_GNU_TESTS +# ifndef TEST_DEFINE_GNU +# error Expected definition TEST_DEFINE_GNU +# endif +#endif + +#include <string.h> + +int main() +{ + return (strcmp(NEEDS_ESCAPE, "E$CAPE") == 0 + && strcmp(EXPECTED_C_COMPILER_VERSION, TEST_C_COMPILER_VERSION) == 0 + && strcmp(EXPECTED_CXX_COMPILER_VERSION, TEST_CXX_COMPILER_VERSION) == 0 + && TEST_C_COMPILER_VERSION_EQUALITY == 1 + && TEST_CXX_COMPILER_VERSION_EQUALITY == 1) ? 0 : 1; +} diff --git a/Tests/CompileOptions/other.cpp b/Tests/CompileOptions/other.cpp new file mode 100644 index 000000000..0e3437579 --- /dev/null +++ b/Tests/CompileOptions/other.cpp @@ -0,0 +1,5 @@ + +void foo(void) +{ + +} diff --git a/Tests/Complex/CMakeLists.txt b/Tests/Complex/CMakeLists.txt index 048f966f6..50dccbe57 100644 --- a/Tests/Complex/CMakeLists.txt +++ b/Tests/Complex/CMakeLists.txt @@ -45,12 +45,12 @@ endmacro() TEST_ARGC(-DCMAKE_ARGV1 -DCMAKE_ARGV2 -DCMAKE_ARGV3 -DCMAKE_ARGV4) macro(TEST_VAR_ARG fa) - if("${ARGV}" MATCHES "^1;2;3$") + if("${ARGV}" STREQUAL "1;2;3") message(STATUS "ARGV works") else() message(FATAL_ERROR "ARGV does not work; got \"${ARGV}\" instead of \"1;2;3\"") endif() - if("${ARGN}" MATCHES "^2;3$") + if("${ARGN}" STREQUAL "2;3") message(STATUS "ARGN works") else() message(FATAL_ERROR "ARGV does not work; got \"${ARGN}\" instead of \"2;3\"") @@ -163,7 +163,7 @@ execute_process( COMMAND ${CMAKE_COMMAND} -E echo "ABCDEFG" OUTPUT_VARIABLE TEST_OUT ) -if("${TEST_OUT}" MATCHES "^ABCDEFG\n$") +if("${TEST_OUT}" STREQUAL "ABCDEFG\n") else() message(SEND_ERROR "EXECUTE_PROCESS output test failed: [${TEST_OUT}]") endif() @@ -177,7 +177,7 @@ endif() # ERROR_QUIET # RESULT_VARIABLE RESULT # ) -# if("${RESULT}" MATCHES "^0$") +# if("${RESULT}" STREQUAL "0") # message(SEND_ERROR # "EXECUTE_PROCESS result test failed with RESULT=[${RESULT}]") # else() @@ -387,10 +387,7 @@ if(NOT RESULT) message(SEND_ERROR "string(REGEX MATCHALL ... ) test failed.") endif() string(REGEX REPLACE ".([bd])." "[\\1]" RESULT "a(b)c(d)e") -if("x${RESULT}" MATCHES "^xa\\[b\\]c\\[d\\]e$") - set(STRING_REGEX_PASSED 1) -endif() -if(NOT STRING_REGEX_PASSED) +if(NOT RESULT STREQUAL "a[b]c[d]e") message(SEND_ERROR "string(REGEX REPLACE ... ) test failed (\"${RESULT}\" v. \"a[b]c[d]e\")") endif() diff --git a/Tests/Complex/Executable/complex.cxx b/Tests/Complex/Executable/complex.cxx index 27d70adc8..e904f2897 100644 --- a/Tests/Complex/Executable/complex.cxx +++ b/Tests/Complex/Executable/complex.cxx @@ -635,86 +635,6 @@ int main() } // ---------------------------------------------------------------------- - // Test FIND_FILE, FIND_PATH and various GET_FILENAME_COMPONENT combinations - -#ifndef FILENAME_VAR_PATH_NAME - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_PATH_NAME is not defined."); -#else - if((strcmp(FILENAME_VAR_PATH_NAME, "Complex") == 0) || - (strcmp(FILENAME_VAR_PATH_NAME, "ComplexOneConfig") == 0)) - { - cmPassed("FILENAME_VAR_PATH_NAME == ", FILENAME_VAR_PATH_NAME); - } - else - { - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_PATH_NAME == ", FILENAME_VAR_PATH_NAME); - } -#endif - -#ifndef FILENAME_VAR_NAME - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_NAME is not defined."); -#else - if(strcmp(FILENAME_VAR_NAME, "VarTests.cmake") != 0) - { - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_NAME == ", FILENAME_VAR_NAME); - } - else - { - cmPassed("FILENAME_VAR_NAME == ", FILENAME_VAR_NAME); - } -#endif - -#ifndef FILENAME_VAR_EXT - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_EXT is not defined."); -#else - if(strcmp(FILENAME_VAR_EXT, ".cmake") != 0) - { - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_EXT == ", FILENAME_VAR_EXT); - } - else - { - cmPassed("FILENAME_VAR_EXT == ", FILENAME_VAR_EXT); - } -#endif - -#ifndef FILENAME_VAR_NAME_WE - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_NAME_WE is not defined."); -#else - if(strcmp(FILENAME_VAR_NAME_WE, "VarTests") != 0) - { - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_NAME_WE == ", FILENAME_VAR_NAME_WE); - } - else - { - cmPassed("FILENAME_VAR_NAME_WE == ", FILENAME_VAR_NAME_WE); - } -#endif - -#ifndef PATH_VAR_NAME - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "PATH_VAR_NAME is not defined."); -#else - if((strcmp(PATH_VAR_NAME, "Complex") == 0) || - (strcmp(PATH_VAR_NAME, "ComplexOneConfig") == 0)) - { - cmPassed("PATH_VAR_NAME == ", PATH_VAR_NAME); - } - else - { - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "PATH_VAR_NAME == ", PATH_VAR_NAME); - } -#endif - - // ---------------------------------------------------------------------- // Test LOAD_CACHE #ifndef CACHE_TEST_VAR1 diff --git a/Tests/Complex/VarTests.cmake b/Tests/Complex/VarTests.cmake index 52ec1fc8e..70b803a1e 100644 --- a/Tests/Complex/VarTests.cmake +++ b/Tests/Complex/VarTests.cmake @@ -182,17 +182,3 @@ set(FOREACH_CONCAT "") foreach (INDEX a;b;c;d;e;f;g) set(FOREACH_CONCAT "${FOREACH_CONCAT}${INDEX}") endforeach() - -# -# Test FIND_FILE, FIND_PATH and various GET_FILENAME_COMPONENT combinations -# -find_file(FILENAME_VAR "VarTests.cmake" ${Complex_SOURCE_DIR}) - -get_filename_component(FILENAME_VAR_PATH ${FILENAME_VAR} PATH) -get_filename_component(FILENAME_VAR_PATH_NAME ${FILENAME_VAR_PATH} NAME) -get_filename_component(FILENAME_VAR_NAME ${FILENAME_VAR} NAME) -get_filename_component(FILENAME_VAR_EXT ${FILENAME_VAR} EXT) -get_filename_component(FILENAME_VAR_NAME_WE ${FILENAME_VAR} NAME_WE CACHE) - -find_path(PATH_VAR "cmTestConfigure.h.in" ${Complex_SOURCE_DIR}) -get_filename_component(PATH_VAR_NAME ${PATH_VAR} NAME) diff --git a/Tests/Complex/cmTestConfigure.h.in b/Tests/Complex/cmTestConfigure.h.in index 7741b6fd5..d7424b184 100644 --- a/Tests/Complex/cmTestConfigure.h.in +++ b/Tests/Complex/cmTestConfigure.h.in @@ -15,15 +15,6 @@ // Test WHILE #define WHILE_VALUE ${while_var} -// Test FIND_FILE, FIND_PATH and various GET_FILENAME_COMPONENT combinations - -#define FILENAME_VAR_PATH_NAME "${FILENAME_VAR_PATH_NAME}" -#define FILENAME_VAR_NAME "${FILENAME_VAR_NAME}" -#define FILENAME_VAR_EXT "${FILENAME_VAR_EXT}" -#define FILENAME_VAR_NAME_WE "${FILENAME_VAR_NAME_WE}" - -#define PATH_VAR_NAME "${PATH_VAR_NAME}" - // Test LOAD_CACHE #define CACHE_TEST_VAR1 "${CACHE_TEST_VAR1}" diff --git a/Tests/ComplexOneConfig/CMakeLists.txt b/Tests/ComplexOneConfig/CMakeLists.txt index b0748fe3d..cbb42860d 100644 --- a/Tests/ComplexOneConfig/CMakeLists.txt +++ b/Tests/ComplexOneConfig/CMakeLists.txt @@ -45,12 +45,12 @@ endmacro() TEST_ARGC(-DCMAKE_ARGV1 -DCMAKE_ARGV2 -DCMAKE_ARGV3 -DCMAKE_ARGV4) macro(TEST_VAR_ARG fa) - if("${ARGV}" MATCHES "^1;2;3$") + if("${ARGV}" STREQUAL "1;2;3") message(STATUS "ARGV works") else() message(FATAL_ERROR "ARGV does not work; got \"${ARGV}\" instead of \"1;2;3\"") endif() - if("${ARGN}" MATCHES "^2;3$") + if("${ARGN}" STREQUAL "2;3") message(STATUS "ARGN works") else() message(FATAL_ERROR "ARGV does not work; got \"${ARGN}\" instead of \"2;3\"") @@ -163,7 +163,7 @@ execute_process( COMMAND ${CMAKE_COMMAND} -E echo "ABCDEFG" OUTPUT_VARIABLE TEST_OUT ) -if("${TEST_OUT}" MATCHES "^ABCDEFG\n$") +if("${TEST_OUT}" STREQUAL "ABCDEFG\n") else() message(SEND_ERROR "EXECUTE_PROCESS output test failed: [${TEST_OUT}]") endif() @@ -177,7 +177,7 @@ endif() # ERROR_QUIET # RESULT_VARIABLE RESULT # ) -# if("${RESULT}" MATCHES "^0$") +# if("${RESULT}" STREQUAL "0") # message(SEND_ERROR # "EXECUTE_PROCESS result test failed with RESULT=[${RESULT}]") # else() @@ -357,10 +357,7 @@ if(NOT RESULT) message(SEND_ERROR "string(REGEX MATCHALL ... ) test failed.") endif() string(REGEX REPLACE ".([bd])." "[\\1]" RESULT "a(b)c(d)e") -if("x${RESULT}" MATCHES "^xa\\[b\\]c\\[d\\]e$") - set(STRING_REGEX_PASSED 1) -endif() -if(NOT STRING_REGEX_PASSED) +if(NOT RESULT STREQUAL "a[b]c[d]e") message(SEND_ERROR "string(REGEX REPLACE ... ) test failed (\"${RESULT}\" v. \"a[b]c[d]e\")") endif() diff --git a/Tests/ComplexOneConfig/Executable/complex.cxx b/Tests/ComplexOneConfig/Executable/complex.cxx index 27d70adc8..e904f2897 100644 --- a/Tests/ComplexOneConfig/Executable/complex.cxx +++ b/Tests/ComplexOneConfig/Executable/complex.cxx @@ -635,86 +635,6 @@ int main() } // ---------------------------------------------------------------------- - // Test FIND_FILE, FIND_PATH and various GET_FILENAME_COMPONENT combinations - -#ifndef FILENAME_VAR_PATH_NAME - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_PATH_NAME is not defined."); -#else - if((strcmp(FILENAME_VAR_PATH_NAME, "Complex") == 0) || - (strcmp(FILENAME_VAR_PATH_NAME, "ComplexOneConfig") == 0)) - { - cmPassed("FILENAME_VAR_PATH_NAME == ", FILENAME_VAR_PATH_NAME); - } - else - { - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_PATH_NAME == ", FILENAME_VAR_PATH_NAME); - } -#endif - -#ifndef FILENAME_VAR_NAME - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_NAME is not defined."); -#else - if(strcmp(FILENAME_VAR_NAME, "VarTests.cmake") != 0) - { - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_NAME == ", FILENAME_VAR_NAME); - } - else - { - cmPassed("FILENAME_VAR_NAME == ", FILENAME_VAR_NAME); - } -#endif - -#ifndef FILENAME_VAR_EXT - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_EXT is not defined."); -#else - if(strcmp(FILENAME_VAR_EXT, ".cmake") != 0) - { - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_EXT == ", FILENAME_VAR_EXT); - } - else - { - cmPassed("FILENAME_VAR_EXT == ", FILENAME_VAR_EXT); - } -#endif - -#ifndef FILENAME_VAR_NAME_WE - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_NAME_WE is not defined."); -#else - if(strcmp(FILENAME_VAR_NAME_WE, "VarTests") != 0) - { - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "FILENAME_VAR_NAME_WE == ", FILENAME_VAR_NAME_WE); - } - else - { - cmPassed("FILENAME_VAR_NAME_WE == ", FILENAME_VAR_NAME_WE); - } -#endif - -#ifndef PATH_VAR_NAME - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "PATH_VAR_NAME is not defined."); -#else - if((strcmp(PATH_VAR_NAME, "Complex") == 0) || - (strcmp(PATH_VAR_NAME, "ComplexOneConfig") == 0)) - { - cmPassed("PATH_VAR_NAME == ", PATH_VAR_NAME); - } - else - { - cmFailed("the FIND_FILE or GET_FILENAME_COMPONENT command is broken, " - "PATH_VAR_NAME == ", PATH_VAR_NAME); - } -#endif - - // ---------------------------------------------------------------------- // Test LOAD_CACHE #ifndef CACHE_TEST_VAR1 diff --git a/Tests/ComplexOneConfig/VarTests.cmake b/Tests/ComplexOneConfig/VarTests.cmake index 52ec1fc8e..70b803a1e 100644 --- a/Tests/ComplexOneConfig/VarTests.cmake +++ b/Tests/ComplexOneConfig/VarTests.cmake @@ -182,17 +182,3 @@ set(FOREACH_CONCAT "") foreach (INDEX a;b;c;d;e;f;g) set(FOREACH_CONCAT "${FOREACH_CONCAT}${INDEX}") endforeach() - -# -# Test FIND_FILE, FIND_PATH and various GET_FILENAME_COMPONENT combinations -# -find_file(FILENAME_VAR "VarTests.cmake" ${Complex_SOURCE_DIR}) - -get_filename_component(FILENAME_VAR_PATH ${FILENAME_VAR} PATH) -get_filename_component(FILENAME_VAR_PATH_NAME ${FILENAME_VAR_PATH} NAME) -get_filename_component(FILENAME_VAR_NAME ${FILENAME_VAR} NAME) -get_filename_component(FILENAME_VAR_EXT ${FILENAME_VAR} EXT) -get_filename_component(FILENAME_VAR_NAME_WE ${FILENAME_VAR} NAME_WE CACHE) - -find_path(PATH_VAR "cmTestConfigure.h.in" ${Complex_SOURCE_DIR}) -get_filename_component(PATH_VAR_NAME ${PATH_VAR} NAME) diff --git a/Tests/ComplexOneConfig/cmTestConfigure.h.in b/Tests/ComplexOneConfig/cmTestConfigure.h.in index 7741b6fd5..d7424b184 100644 --- a/Tests/ComplexOneConfig/cmTestConfigure.h.in +++ b/Tests/ComplexOneConfig/cmTestConfigure.h.in @@ -15,15 +15,6 @@ // Test WHILE #define WHILE_VALUE ${while_var} -// Test FIND_FILE, FIND_PATH and various GET_FILENAME_COMPONENT combinations - -#define FILENAME_VAR_PATH_NAME "${FILENAME_VAR_PATH_NAME}" -#define FILENAME_VAR_NAME "${FILENAME_VAR_NAME}" -#define FILENAME_VAR_EXT "${FILENAME_VAR_EXT}" -#define FILENAME_VAR_NAME_WE "${FILENAME_VAR_NAME_WE}" - -#define PATH_VAR_NAME "${PATH_VAR_NAME}" - // Test LOAD_CACHE #define CACHE_TEST_VAR1 "${CACHE_TEST_VAR1}" diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt index d3ced3ff9..30daa7dea 100644 --- a/Tests/CustomCommand/CMakeLists.txt +++ b/Tests/CustomCommand/CMakeLists.txt @@ -123,6 +123,19 @@ add_custom_command( COMMENT "Running TDocument post-build commands" ) +# Setup a custom target that will fail if the POST_BUILD custom command +# isn't run before it. +add_custom_command( + OUTPUT doc3post.txt + DEPENDS ${PROJECT_BINARY_DIR}/doc2post.txt + COMMAND ${CMAKE_COMMAND} -E echo " Copying doc2pre.txt to doc3post.txt." + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc2post.txt + ${PROJECT_BINARY_DIR}/doc3post.txt + COMMENT "Running TDocument post-build dependent custom command" + ) +add_custom_target(doc3Post ALL DEPENDS doc3post.txt) +add_dependencies(doc3Post TDocument) + ################################################################ # # Test using a multistep generated file diff --git a/Tests/EmptyProperty/CMakeLists.txt b/Tests/EmptyProperty/CMakeLists.txt new file mode 100644 index 000000000..39e75f36a --- /dev/null +++ b/Tests/EmptyProperty/CMakeLists.txt @@ -0,0 +1,9 @@ +project (EmptyProperty) + +set_property(DIRECTORY APPEND + PROPERTY + COMPILE_DEFINITIONS) + +include(CTest) + +add_executable(EmptyProperty EmptyProperty.cxx) diff --git a/Tests/EmptyProperty/EmptyProperty.cxx b/Tests/EmptyProperty/EmptyProperty.cxx new file mode 100644 index 000000000..78f2de106 --- /dev/null +++ b/Tests/EmptyProperty/EmptyProperty.cxx @@ -0,0 +1 @@ +int main(void) { return 0; } diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index be48483da..72ae78f57 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -99,7 +99,6 @@ macro(add_include_lib _libName) set_property(TARGET ${_libName} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/${_libName}>" - "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/${_libName}>" ) if (NOT "${ARGV1}" STREQUAL "NO_HEADER") file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}/${_libName}.h" "// no content\n") @@ -140,6 +139,12 @@ install(FILES ) add_include_lib(testLibIncludeRequired6) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired7/testLibIncludeRequired7.h" "// No content\n") +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/testLibIncludeRequired7/testLibIncludeRequired7.h" + DESTINATION include/testLibIncludeRequired7 +) + set_property(TARGET testLibRequired APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:testLibIncludeRequired1,INTERFACE_INCLUDE_DIRECTORIES> @@ -154,6 +159,7 @@ set_property(TARGET testLibRequired APPEND PROPERTY $<BUILD_INTERFACE:$<TARGET_PROPERTY:testLibIncludeRequired5,INTERFACE_INCLUDE_DIRECTORIES>> # Test that the below is non-fatal $<$<STREQUAL:one,two>:$<TARGET_PROPERTY:not_a_target,INTERFACE_INCLUDE_DIRECTORIES>> + $<INSTALL_INTERFACE:include/testLibIncludeRequired7;include/testLibIncludeRequired4> ) set_property(TARGET testLibRequired APPEND PROPERTY @@ -162,9 +168,10 @@ set_property(TARGET testLibRequired APPEND PROPERTY $<BUILD_INTERFACE:BuildOnly_DEFINE> $<INSTALL_INTERFACE:InstallOnly_DEFINE> ) - include(GenerateExportHeader) +add_subdirectory(renamed) + add_library(testSharedLibRequired SHARED testSharedLibRequired.cpp) generate_export_header(testSharedLibRequired) set_property(TARGET testSharedLibRequired @@ -180,8 +187,10 @@ install(FILES DESTINATION include/testSharedLibRequired ) set_property(TARGET testSharedLibRequired APPEND PROPERTY - INTERFACE_INCLUDE_DIRECTORIES "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/testSharedLibRequired>" - "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>" + INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>" +) +set_property(TARGET testSharedLibRequired APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS USING_TESTSHAREDLIBREQUIRED ) set_property(TARGET testSharedLibRequired APPEND PROPERTY @@ -199,6 +208,39 @@ set_property(TARGET testSharedLibRequired PROPERTY INTERFACE_CUSTOM_STRING testcontent ) +set_property(TARGET testSharedLibRequired APPEND PROPERTY + INTERFACE_COMPILE_OPTIONS + $<$<CXX_COMPILER_ID:GNU>:-DCUSTOM_COMPILE_OPTION> +) + +add_library(testSharedLibRequiredUser SHARED testSharedLibRequiredUser.cpp) +generate_export_header(testSharedLibRequiredUser) +# LINK_PRIVATE so that it appears in the LINK_DEPENDENT_LIBRARIES, but not +# the INTERFACE_LINK_LIBRARIES. +set_property(TARGET testSharedLibRequiredUser APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>" +) +target_link_libraries(testSharedLibRequiredUser LINK_PRIVATE testSharedLibRequired) +install(FILES + "${CMAKE_CURRENT_SOURCE_DIR}/testSharedLibRequiredUser.h" + "${CMAKE_CURRENT_BINARY_DIR}/testsharedlibrequireduser_export.h" + DESTINATION include/testSharedLibRequiredUser +) + +cmake_policy(SET CMP0022 NEW) +add_library(testSharedLibRequiredUser2 SHARED testSharedLibRequiredUser2.cpp) +generate_export_header(testSharedLibRequiredUser2) +set_property(TARGET testSharedLibRequiredUser2 APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>" +) +set_property(TARGET testSharedLibRequiredUser2 PROPERTY LINK_LIBRARIES testSharedLibRequired) +set_property(TARGET testSharedLibRequiredUser2 PROPERTY INTERFACE_LINK_LIBRARIES testSharedLibRequired) +install(FILES + "${CMAKE_CURRENT_SOURCE_DIR}/testSharedLibRequiredUser2.h" + "${CMAKE_CURRENT_BINARY_DIR}/testsharedlibrequireduser2_export.h" + DESTINATION include/testSharedLibRequiredUser2 +) +cmake_policy(SET CMP0022 OLD) add_library(testSharedLibDepends SHARED testSharedLibDepends.cpp) set_property(TARGET testSharedLibDepends APPEND PROPERTY @@ -219,25 +261,80 @@ set_property(TARGET testSharedLibDepends APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/testSharedLibDepends>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>" ) -set_property(TARGET testSharedLibDepends APPEND PROPERTY - LINK_INTERFACE_LIBRARIES - $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:$<TARGET_NAME:testSharedLibRequired>> -) # LINK_PRIVATE because the LINK_INTERFACE_LIBRARIES is specified above. target_link_libraries(testSharedLibDepends LINK_PRIVATE testSharedLibRequired) +target_link_libraries(testSharedLibDepends LINK_PUBLIC renamed_on_export) +target_link_libraries(testSharedLibDepends LINK_INTERFACE_LIBRARIES + $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:$<TARGET_NAME:testSharedLibRequired>>) + +add_library(cmp0022OLD SHARED cmp0022_vs6_1.cpp) +generate_export_header(cmp0022OLD BASE_NAME cmp0022) +target_include_directories(cmp0022OLD PUBLIC + "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>" + "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/cmp0022>" +) +cmake_policy(SET CMP0022 NEW) +add_library(cmp0022NEW SHARED cmp0022_vs6_1.cpp) +set_property(TARGET cmp0022NEW PROPERTY DEFINE_SYMBOL cmp0022OLD_EXPORTS) +target_include_directories(cmp0022NEW PUBLIC + "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>" + "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/cmp0022>" +) +cmake_policy(SET CMP0022 OLD) +install(FILES + "${CMAKE_CURRENT_SOURCE_DIR}/cmp0022.h" + "${CMAKE_CURRENT_BINARY_DIR}/cmp0022_export.h" + DESTINATION include/cmp0022 +) + +set_property(TARGET testLib2 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USING_TESTLIB2) +set_property(TARGET testLib3 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USING_TESTLIB3) + +set_property(TARGET cmp0022NEW APPEND PROPERTY INTERFACE_LINK_LIBRARIES testLib2) +# set_property(TARGET cmp0022NEW APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLibIncludeRequired2) # TODO: Test for error +set_property(TARGET cmp0022OLD APPEND PROPERTY INTERFACE_LINK_LIBRARIES testLib2) +set_property(TARGET cmp0022OLD APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLib3) + +add_library(noIncludesInterface empty.cpp) install(TARGETS testLibRequired - testLibIncludeRequired1 - testLibIncludeRequired2 - testLibIncludeRequired3 - testLibIncludeRequired4 - testLibIncludeRequired5 - testLibIncludeRequired6 - testSharedLibRequired - EXPORT RequiredExp DESTINATION lib ) + EXPORT RequiredExp DESTINATION lib + INCLUDES DESTINATION + installIncludesTest + $<INSTALL_PREFIX>/installIncludesTest2 + ) +install(TARGETS + testLibIncludeRequired1 + testLibIncludeRequired2 + testLibIncludeRequired3 + testLibIncludeRequired4 + testLibIncludeRequired5 + testLibIncludeRequired6 + testSharedLibRequired + testSharedLibRequiredUser + testSharedLibRequiredUser2 + noIncludesInterface + EXPORT RequiredExp DESTINATION lib + INCLUDES DESTINATION + $<INSTALL_PREFIX>/include/$<TARGET_PROPERTY:NAME> +) install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredTargets.cmake DESTINATION lib/cmake/testLibRequired) +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest/installIncludesTest.h" "// No content\n") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest2") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest2/installIncludesTest2.h" "// No content\n") +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest/installIncludesTest.h" + DESTINATION installIncludesTest +) +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest2/installIncludesTest2.h" + DESTINATION installIncludesTest2 +) + install(TARGETS testLibDepends testSharedLibDepends EXPORT DependsExp DESTINATION lib ) install(EXPORT DependsExp FILE testLibDependsTargets.cmake DESTINATION lib/cmake/testLibDepends) @@ -268,6 +365,7 @@ install( testExe2lib testLib4lib testLib4libdbg testLib4libopt testLib6 testLibCycleA testLibCycleB + cmp0022NEW cmp0022OLD EXPORT exp RUNTIME DESTINATION bin LIBRARY DESTINATION lib NAMELINK_SKIP @@ -275,6 +373,12 @@ install( FRAMEWORK DESTINATION Frameworks BUNDLE DESTINATION Applications ) +if (APPLE) + file(COPY testLib4.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/testLib4.framework/Headers) + file(COPY testLib4.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Debug/testLib4.framework/Headers) + file(COPY testLib4.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Release/testLib4.framework/Headers) + install(FILES testLib4.h DESTINATION Frameworks/testLib4.framework/Headers) +endif() install( TARGETS testExe2libImp testLib3Imp @@ -310,7 +414,9 @@ add_subdirectory(sublib) # For CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE test. # Export from build tree. export(TARGETS testExe1 testLib1 testLib2 testLib3 testExe2libImp testLib3Imp testLib3ImpDep subdirlib - testSharedLibRequired testSharedLibDepends + testSharedLibRequired testSharedLibRequiredUser testSharedLibRequiredUser2 + testSharedLibDepends renamed_on_export + cmp0022NEW cmp0022OLD NAMESPACE bld_ FILE ExportBuildTree.cmake ) diff --git a/Tests/ExportImport/Export/cmp0022.cpp b/Tests/ExportImport/Export/cmp0022.cpp new file mode 100644 index 000000000..bef8e6180 --- /dev/null +++ b/Tests/ExportImport/Export/cmp0022.cpp @@ -0,0 +1,7 @@ + +#include "cmp0022.h" + +int cmp0022() +{ + return 0; +} diff --git a/Tests/ExportImport/Export/cmp0022.h b/Tests/ExportImport/Export/cmp0022.h new file mode 100644 index 000000000..32bf71a44 --- /dev/null +++ b/Tests/ExportImport/Export/cmp0022.h @@ -0,0 +1,4 @@ + +#include "cmp0022_export.h" + +int CMP0022_EXPORT cmp0022(); diff --git a/Tests/ExportImport/Export/cmp0022_vs6_1.cpp b/Tests/ExportImport/Export/cmp0022_vs6_1.cpp new file mode 100644 index 000000000..a6ec83805 --- /dev/null +++ b/Tests/ExportImport/Export/cmp0022_vs6_1.cpp @@ -0,0 +1 @@ +#include "cmp0022.cpp" diff --git a/Tests/ExportImport/Export/cmp0022_vs6_2.cpp b/Tests/ExportImport/Export/cmp0022_vs6_2.cpp new file mode 100644 index 000000000..a6ec83805 --- /dev/null +++ b/Tests/ExportImport/Export/cmp0022_vs6_2.cpp @@ -0,0 +1 @@ +#include "cmp0022.cpp" diff --git a/Tests/ExportImport/Export/empty.cpp b/Tests/ExportImport/Export/empty.cpp new file mode 100644 index 000000000..1787013f6 --- /dev/null +++ b/Tests/ExportImport/Export/empty.cpp @@ -0,0 +1,4 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty() { return 0; } diff --git a/Tests/ExportImport/Export/renamed/CMakeLists.txt b/Tests/ExportImport/Export/renamed/CMakeLists.txt new file mode 100644 index 000000000..a76325139 --- /dev/null +++ b/Tests/ExportImport/Export/renamed/CMakeLists.txt @@ -0,0 +1,20 @@ + +add_library(renamed_on_export SHARED renamed.cxx) +generate_export_header(renamed_on_export) +target_include_directories(renamed_on_export + PUBLIC "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/renamed>" + "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>" +) +set_property(TARGET renamed_on_export + PROPERTY + EXPORT_NAME renamed +) + +install(FILES + "${CMAKE_CURRENT_SOURCE_DIR}/renamed.h" + "${CMAKE_CURRENT_BINARY_DIR}/renamed_on_export_export.h" + DESTINATION include/renamed +) + +install(TARGETS renamed_on_export + EXPORT exp DESTINATION lib ) diff --git a/Tests/ExportImport/Export/renamed/renamed.cxx b/Tests/ExportImport/Export/renamed/renamed.cxx new file mode 100644 index 000000000..b3e3e7e12 --- /dev/null +++ b/Tests/ExportImport/Export/renamed/renamed.cxx @@ -0,0 +1,7 @@ + +#include "renamed.h" + +int Renamed::foo() +{ + return 0; +} diff --git a/Tests/ExportImport/Export/renamed/renamed.h b/Tests/ExportImport/Export/renamed/renamed.h new file mode 100644 index 000000000..06ac601d5 --- /dev/null +++ b/Tests/ExportImport/Export/renamed/renamed.h @@ -0,0 +1,12 @@ + +#ifndef RENAMED_H +#define RENAMED_H + +#include "renamed_on_export_export.h" + +struct RENAMED_ON_EXPORT_EXPORT Renamed +{ + int foo(); +}; + +#endif diff --git a/Tests/ExportImport/Export/testLib4.h b/Tests/ExportImport/Export/testLib4.h new file mode 100644 index 000000000..9eeda7c0e --- /dev/null +++ b/Tests/ExportImport/Export/testLib4.h @@ -0,0 +1,2 @@ + +#define TESTLIB4_H diff --git a/Tests/ExportImport/Export/testSharedLibDepends.cpp b/Tests/ExportImport/Export/testSharedLibDepends.cpp index e27920725..962223faf 100644 --- a/Tests/ExportImport/Export/testSharedLibDepends.cpp +++ b/Tests/ExportImport/Export/testSharedLibDepends.cpp @@ -4,5 +4,6 @@ int TestSharedLibDepends::foo() { TestSharedLibRequired req; - return req.foo(); + Renamed renamed; + return req.foo() + renamed.foo(); } diff --git a/Tests/ExportImport/Export/testSharedLibDepends.h b/Tests/ExportImport/Export/testSharedLibDepends.h index b93143a5c..8b2f84eb3 100644 --- a/Tests/ExportImport/Export/testSharedLibDepends.h +++ b/Tests/ExportImport/Export/testSharedLibDepends.h @@ -5,6 +5,7 @@ #include "testsharedlibdepends_export.h" #include "testSharedLibRequired.h" +#include "renamed.h" struct TESTSHAREDLIBDEPENDS_EXPORT TestSharedLibDepends { diff --git a/Tests/ExportImport/Export/testSharedLibRequiredUser.cpp b/Tests/ExportImport/Export/testSharedLibRequiredUser.cpp new file mode 100644 index 000000000..558000517 --- /dev/null +++ b/Tests/ExportImport/Export/testSharedLibRequiredUser.cpp @@ -0,0 +1,10 @@ + +#include "testSharedLibRequiredUser.h" + +#include "testSharedLibRequired.h" + +int TestSharedLibRequiredUser::foo() +{ + TestSharedLibRequired req; + return req.foo(); +} diff --git a/Tests/ExportImport/Export/testSharedLibRequiredUser.h b/Tests/ExportImport/Export/testSharedLibRequiredUser.h new file mode 100644 index 000000000..58bcaa507 --- /dev/null +++ b/Tests/ExportImport/Export/testSharedLibRequiredUser.h @@ -0,0 +1,12 @@ + +#ifndef TESTSHAREDLIBREQUIREDUSER_H +#define TESTSHAREDLIBREQUIREDUSER_H + +#include "testsharedlibrequireduser_export.h" + +struct TESTSHAREDLIBREQUIREDUSER_EXPORT TestSharedLibRequiredUser +{ + int foo(); +}; + +#endif diff --git a/Tests/ExportImport/Export/testSharedLibRequiredUser2.cpp b/Tests/ExportImport/Export/testSharedLibRequiredUser2.cpp new file mode 100644 index 000000000..d671bf065 --- /dev/null +++ b/Tests/ExportImport/Export/testSharedLibRequiredUser2.cpp @@ -0,0 +1,8 @@ + +#include "testSharedLibRequiredUser2.h" + +TestSharedLibRequired TestSharedLibRequiredUser2::foo() +{ + TestSharedLibRequired req; + return req; +} diff --git a/Tests/ExportImport/Export/testSharedLibRequiredUser2.h b/Tests/ExportImport/Export/testSharedLibRequiredUser2.h new file mode 100644 index 000000000..a13294028 --- /dev/null +++ b/Tests/ExportImport/Export/testSharedLibRequiredUser2.h @@ -0,0 +1,14 @@ + +#ifndef TESTSHAREDLIBREQUIREDUSER2_H +#define TESTSHAREDLIBREQUIREDUSER2_H + +#include "testsharedlibrequireduser2_export.h" + +#include "testSharedLibRequired.h" + +struct TESTSHAREDLIBREQUIREDUSER2_EXPORT TestSharedLibRequiredUser2 +{ + TestSharedLibRequired foo(); +}; + +#endif diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 0337130f4..2627354ac 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -68,6 +68,16 @@ target_link_libraries(imp_testExe1b bld_testLibCycleA ) +add_executable(cmp0022OLD_test cmp0022OLD_test_vs6_1.cpp) +target_link_libraries(cmp0022OLD_test bld_cmp0022OLD) +add_executable(cmp0022NEW_test cmp0022NEW_test_vs6_1.cpp) +target_link_libraries(cmp0022NEW_test bld_cmp0022NEW) + +add_executable(cmp0022OLD_exp_test cmp0022OLD_test_vs6_2.cpp) +target_link_libraries(cmp0022OLD_exp_test exp_cmp0022OLD) +add_executable(cmp0022NEW_exp_test cmp0022NEW_test_vs6_2.cpp) +target_link_libraries(cmp0022NEW_exp_test exp_cmp0022NEW) + # Try building a plugin to an executable imported from the build tree. add_library(imp_mod1b MODULE imp_mod1.c) target_link_libraries(imp_mod1b bld_testExe2) @@ -169,6 +179,13 @@ target_compile_definitions(deps_shared_iface $<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH> ) +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(deps_shared_iface + PRIVATE + "DO_GNU_TESTS" + ) +endif() + if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") include(CheckCXXCompilerFlag) check_cxx_compiler_flag(-fPIE run_pic_test) @@ -183,19 +200,68 @@ else() endif() endif() +add_executable(exp_renamed_test renamed_test.cpp) +target_link_libraries(exp_renamed_test exp_renamed) + +add_executable(bld_renamed_test renamed_test.cpp) +target_link_libraries(bld_renamed_test bld_renamed) + if (run_pic_test) target_compile_definitions(deps_shared_iface PRIVATE CHECK_PIC_WORKS) endif() +if(APPLE) + add_subdirectory(framework_interface) +endif() + #----------------------------------------------------------------------------- # Test that targets imported from the build tree have their dependencies # evaluated correctly. The above already tests the same for the install tree. add_executable(deps_shared_iface2 deps_shared_iface.cpp) target_link_libraries(deps_shared_iface2 bld_testSharedLibDepends bld_subdirlib) +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(deps_shared_iface2 + PRIVATE + "DO_GNU_TESTS" + ) +endif() target_compile_definitions(deps_shared_iface2 PRIVATE TEST_SUBDIR_LIB $<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON> $<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON> $<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH> ) + +add_subdirectory(excludedFromAll) + +add_executable(iface_test_bld iface_test.cpp) +target_link_libraries(iface_test_bld bld_testSharedLibDepends) + +set_property(TARGET bld_testSharedLibRequired APPEND PROPERTY + LINK_INTERFACE_LIBRARIES + excludedFromAll +) +get_target_property(_configs bld_testSharedLibRequired IMPORTED_CONFIGURATIONS) +foreach(_config ${_configs}) + set_property(TARGET bld_testSharedLibRequired APPEND PROPERTY + IMPORTED_LINK_INTERFACE_LIBRARIES_${_config} + excludedFromAll + ) +endforeach() +unset(_configs) +add_executable(iface_test_exp iface_test.cpp) +target_link_libraries(iface_test_exp testSharedLibDepends) + +set_property(TARGET testSharedLibDepends APPEND PROPERTY + LINK_INTERFACE_LIBRARIES + excludedFromAll +) +get_target_property(_configs testSharedLibDepends IMPORTED_CONFIGURATIONS) +foreach(_config ${_configs}) + set_property(TARGET testSharedLibDepends APPEND PROPERTY + IMPORTED_LINK_INTERFACE_LIBRARIES_${_config} + excludedFromAll + ) +endforeach() +unset(_configs) diff --git a/Tests/ExportImport/Import/A/cmp0022NEW_test.cpp b/Tests/ExportImport/Import/A/cmp0022NEW_test.cpp new file mode 100644 index 000000000..587834987 --- /dev/null +++ b/Tests/ExportImport/Import/A/cmp0022NEW_test.cpp @@ -0,0 +1,12 @@ + +#ifndef USING_TESTLIB2 +#error Expected USING_TESTLIB2 +#endif +#ifdef USING_TESTLIB3 +#error Unexpected USING_TESTLIB3 +#endif + +int main(void) +{ + return 0; +} diff --git a/Tests/ExportImport/Import/A/cmp0022NEW_test_vs6_1.cpp b/Tests/ExportImport/Import/A/cmp0022NEW_test_vs6_1.cpp new file mode 100644 index 000000000..033b7463f --- /dev/null +++ b/Tests/ExportImport/Import/A/cmp0022NEW_test_vs6_1.cpp @@ -0,0 +1 @@ +#include "cmp0022NEW_test.cpp" diff --git a/Tests/ExportImport/Import/A/cmp0022NEW_test_vs6_2.cpp b/Tests/ExportImport/Import/A/cmp0022NEW_test_vs6_2.cpp new file mode 100644 index 000000000..033b7463f --- /dev/null +++ b/Tests/ExportImport/Import/A/cmp0022NEW_test_vs6_2.cpp @@ -0,0 +1 @@ +#include "cmp0022NEW_test.cpp" diff --git a/Tests/ExportImport/Import/A/cmp0022OLD_test.cpp b/Tests/ExportImport/Import/A/cmp0022OLD_test.cpp new file mode 100644 index 000000000..e50158b76 --- /dev/null +++ b/Tests/ExportImport/Import/A/cmp0022OLD_test.cpp @@ -0,0 +1,12 @@ + +#ifdef USING_TESTLIB2 +#error Unexpected USING_TESTLIB2 +#endif +#ifndef USING_TESTLIB3 +#error Expected USING_TESTLIB3 +#endif + +int main(void) +{ + return 0; +} diff --git a/Tests/ExportImport/Import/A/cmp0022OLD_test_vs6_1.cpp b/Tests/ExportImport/Import/A/cmp0022OLD_test_vs6_1.cpp new file mode 100644 index 000000000..90d804ce7 --- /dev/null +++ b/Tests/ExportImport/Import/A/cmp0022OLD_test_vs6_1.cpp @@ -0,0 +1 @@ +#include "cmp0022OLD_test.cpp" diff --git a/Tests/ExportImport/Import/A/cmp0022OLD_test_vs6_2.cpp b/Tests/ExportImport/Import/A/cmp0022OLD_test_vs6_2.cpp new file mode 100644 index 000000000..90d804ce7 --- /dev/null +++ b/Tests/ExportImport/Import/A/cmp0022OLD_test_vs6_2.cpp @@ -0,0 +1 @@ +#include "cmp0022OLD_test.cpp" diff --git a/Tests/ExportImport/Import/A/deps_iface.c b/Tests/ExportImport/Import/A/deps_iface.c index e73ca26bf..48a4c44d6 100644 --- a/Tests/ExportImport/Import/A/deps_iface.c +++ b/Tests/ExportImport/Import/A/deps_iface.c @@ -2,6 +2,10 @@ #include "testLibIncludeRequired1.h" #include "testLibIncludeRequired2.h" #include "testLibIncludeRequired6.h" +#include "testLibIncludeRequired7.h" + +#include "installIncludesTest.h" +#include "installIncludesTest2.h" #ifndef testLibRequired_IFACE_DEFINE #error Expected testLibRequired_IFACE_DEFINE diff --git a/Tests/ExportImport/Import/A/deps_shared_iface.cpp b/Tests/ExportImport/Import/A/deps_shared_iface.cpp index 2f0e74a07..d5e4de3c0 100644 --- a/Tests/ExportImport/Import/A/deps_shared_iface.cpp +++ b/Tests/ExportImport/Import/A/deps_shared_iface.cpp @@ -22,6 +22,13 @@ #ifdef TEST_SUBDIR_LIB #include "subdir.h" +#include "renamed.h" +#endif + +#ifdef DO_GNU_TESTS +#ifndef CUSTOM_COMPILE_OPTION +#error Expected CUSTOM_COMPILE_OPTION +#endif #endif int main(int,char **) @@ -31,11 +38,12 @@ int main(int,char **) #ifdef TEST_SUBDIR_LIB SubDirObject sdo; + Renamed ren; #endif return dep.foo() + req.foo() #ifdef TEST_SUBDIR_LIB - + sdo.foo() + + sdo.foo() + ren.foo() #endif ; } diff --git a/Tests/ExportImport/Import/A/excludedFromAll/CMakeLists.txt b/Tests/ExportImport/Import/A/excludedFromAll/CMakeLists.txt new file mode 100644 index 000000000..cd5a59bfe --- /dev/null +++ b/Tests/ExportImport/Import/A/excludedFromAll/CMakeLists.txt @@ -0,0 +1,7 @@ + +set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +include(GenerateExportHeader) +add_library(excludedFromAll SHARED EXCLUDE_FROM_ALL excludedFromAll.cpp) +generate_export_header(excludedFromAll) diff --git a/Tests/ExportImport/Import/A/excludedFromAll/excludedFromAll.cpp b/Tests/ExportImport/Import/A/excludedFromAll/excludedFromAll.cpp new file mode 100644 index 000000000..2269a0402 --- /dev/null +++ b/Tests/ExportImport/Import/A/excludedFromAll/excludedFromAll.cpp @@ -0,0 +1,7 @@ + +#include "excludedFromAll.h" + +int excludedFromAll() +{ + return 0; +} diff --git a/Tests/ExportImport/Import/A/excludedFromAll/excludedFromAll.h b/Tests/ExportImport/Import/A/excludedFromAll/excludedFromAll.h new file mode 100644 index 000000000..4820c76c1 --- /dev/null +++ b/Tests/ExportImport/Import/A/excludedFromAll/excludedFromAll.h @@ -0,0 +1,4 @@ + +#include "excludedfromall_export.h" + +int EXCLUDEDFROMALL_EXPORT excludedFromAll(); diff --git a/Tests/ExportImport/Import/A/framework_interface/CMakeLists.txt b/Tests/ExportImport/Import/A/framework_interface/CMakeLists.txt new file mode 100644 index 000000000..0e0065555 --- /dev/null +++ b/Tests/ExportImport/Import/A/framework_interface/CMakeLists.txt @@ -0,0 +1,9 @@ + +add_library(exp_framework_test framework_test.cpp) +get_target_property(exp_loc exp_testLib4 LOCATION) +target_link_libraries(exp_framework_test ${exp_loc}) + + +add_library(bld_framework_test framework_test.cpp) +get_target_property(bld_loc bld_testLib4 LOCATION) +target_link_libraries(bld_framework_test ${bld_loc}) diff --git a/Tests/ExportImport/Import/A/framework_interface/framework_test.cpp b/Tests/ExportImport/Import/A/framework_interface/framework_test.cpp new file mode 100644 index 000000000..357f64f02 --- /dev/null +++ b/Tests/ExportImport/Import/A/framework_interface/framework_test.cpp @@ -0,0 +1,6 @@ + +#include <testLib4/testLib4.h> + +#ifndef TESTLIB4_H +#error Expected define TESTLIB4_H +#endif diff --git a/Tests/ExportImport/Import/A/iface_test.cpp b/Tests/ExportImport/Import/A/iface_test.cpp new file mode 100644 index 000000000..fa4474bdb --- /dev/null +++ b/Tests/ExportImport/Import/A/iface_test.cpp @@ -0,0 +1,11 @@ + +#ifndef USING_TESTSHAREDLIBREQUIRED +#error Expected USING_TESTSHAREDLIBREQUIRED +#endif + +#include "excludedFromAll.h" + +int main(void) +{ + return excludedFromAll(); +} diff --git a/Tests/ExportImport/Import/A/renamed_test.cpp b/Tests/ExportImport/Import/A/renamed_test.cpp new file mode 100644 index 000000000..e2ee126aa --- /dev/null +++ b/Tests/ExportImport/Import/A/renamed_test.cpp @@ -0,0 +1,8 @@ + +#include "renamed.h" + +int main(int, char **) +{ + Renamed ren; + return ren.foo(); +} diff --git a/Tests/ExportImport/Import/try_compile/CMakeLists.txt b/Tests/ExportImport/Import/try_compile/CMakeLists.txt index 5600dffdf..10884616b 100644 --- a/Tests/ExportImport/Import/try_compile/CMakeLists.txt +++ b/Tests/ExportImport/Import/try_compile/CMakeLists.txt @@ -5,17 +5,32 @@ find_package(testLibRequired 2.5 REQUIRED) include(CheckCXXSourceCompiles) -set(CMAKE_REQUIRED_LIBRARIES Req::testSharedLibRequired) +set(CMAKE_REQUIRED_LIBRARIES Req::testSharedLibRequiredUser) check_cxx_source_compiles( " -#include \"testSharedLibRequired.h\" +#include \"testSharedLibRequiredUser.h\" int main(int argc, char **argv) { - TestSharedLibRequired req; - return req.foo(); + TestSharedLibRequiredUser user; + return user.foo(); } -" SHARED_LIB_REQUIRED) +" SHARED_LIB_DEPENDS) -if(NOT SHARED_LIB_REQUIRED) +if(NOT SHARED_LIB_DEPENDS) + message(SEND_ERROR "try_compile with IMPORTED targets failed!\n\n${OUTPUT}") +endif() + +set(CMAKE_REQUIRED_LIBRARIES Req::testSharedLibRequiredUser2) +check_cxx_source_compiles( + " +#include \"testSharedLibRequiredUser2.h\" +int main(int argc, char **argv) +{ + TestSharedLibRequiredUser2 user; + return user.foo().foo(); +} +" SHARED_LIB_DEPENDS2) + +if(NOT SHARED_LIB_DEPENDS2) message(SEND_ERROR "try_compile with IMPORTED targets failed!\n\n${OUTPUT}") endif() diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index 0008c1656..4d8d7ed25 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required (VERSION 2.8.8) project(GeneratorExpression CXX) +# This test is split into multiple parts as needed to avoid NMake command +# length limits. + add_custom_target(check-part1 ALL COMMAND ${CMAKE_COMMAND} -Dtest_0=$<0:nothing> @@ -60,7 +63,7 @@ add_custom_target(check-part1 ALL -Dtest_colons_4=$<1:C:\\CMake> -Dtest_colons_5=$<1:C:/CMake> -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part1.cmake - COMMAND ${CMAKE_COMMAND} -E echo "check done (part 1 of 2)" + COMMAND ${CMAKE_COMMAND} -E echo "check done (part 1 of 3)" VERBATIM ) @@ -120,7 +123,70 @@ add_custom_target(check-part2 ALL -Dtest_target_includes6=$<TARGET_PROPERTY:empty3,INCLUDE_DIRECTORIES> -Dtest_target_includes7=$<TARGET_PROPERTY:empty1,INTERFACE_INCLUDE_DIRECTORIES> -Dtest_target_includes8=$<TARGET_PROPERTY:empty5,INCLUDE_DIRECTORIES> + -Dtest_arbitrary_content_comma_1=$<1:a,> + -Dtest_arbitrary_content_comma_2=$<1:,a> + -Dtest_arbitrary_content_comma_3=$<1:a,,> + -Dtest_arbitrary_content_comma_4=$<1:,> + -Dtest_arbitrary_content_comma_5=$<1:,,> + -Dtest_arbitrary_content_comma_6=$<1:,,,> + -Dtest_arbitrary_content_comma_7=$<1:,,a> + -Dtest_arbitrary_content_comma_8=$<1:a,,b> + -Dtest_arbitrary_content_comma_9=$<1:a,,b,,> + -Dtest_arbitrary_content_comma_10=$<1:,,a,,b,,> -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part2.cmake - COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 2)" + COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 3)" + VERBATIM +) + +add_library(imported1 SHARED IMPORTED) +set_property(TARGET imported1 PROPERTY IMPORTED_LOCATION_RELEASE release_loc) +set_property(TARGET imported1 PROPERTY IMPORTED_LOCATION_DEBUG debug_loc) +set_property(TARGET imported1 PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG) +set_property(TARGET imported1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES /imported1/include) + +add_library(imported2 SHARED IMPORTED) +set_property(TARGET imported2 PROPERTY IMPORTED_LOCATION_RELEASE release_loc) +set_property(TARGET imported2 PROPERTY IMPORTED_LOCATION_DEBUG debug_loc) +set_property(TARGET imported2 PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG) +set_property(TARGET imported2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES /imported2/include) + +add_library(imported3 SHARED IMPORTED) +set_property(TARGET imported3 PROPERTY IMPORTED_LOCATION_RELEASE release_loc) +set_property(TARGET imported3 PROPERTY IMPORTED_LOCATION_DEBUG debug_loc) +# Both Debug and Release should not be true when this is evaluated. +set_property(TARGET imported3 APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES $<$<CONFIG:DEBUG>:$<TARGET_PROPERTY:imported1,INTERFACE_INCLUDE_DIRECTORIES>>) +set_property(TARGET imported3 APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES $<$<CONFIG:RELEASE>:$<TARGET_PROPERTY:imported2,INTERFACE_INCLUDE_DIRECTORIES>>) + +add_library(imported4 SHARED IMPORTED) +set_property(TARGET imported4 APPEND PROPERTY + INCLUDE_DIRECTORIES $<TARGET_PROPERTY:imported3,INTERFACE_INCLUDE_DIRECTORIES>) + +add_executable(someexe empty.cpp) +add_executable(Alias::SomeExe ALIAS someexe) + +add_library(Alias::SomeLib ALIAS empty1) + +add_custom_target(check-part3 ALL + COMMAND ${CMAKE_COMMAND} + -Dtest_version_greater_1=$<VERSION_GREATER:1.0,1.1.1> + -Dtest_version_greater_2=$<VERSION_GREATER:1.1.1,1.0> + -Dtest_version_less_1=$<VERSION_LESS:1.1.1,1.0> + -Dtest_version_less_2=$<VERSION_LESS:1.0,1.1.1> + -Dtest_version_equal_1=$<VERSION_EQUAL:1.0.1,1.1> + -Dtest_version_equal_2=$<VERSION_EQUAL:1.1,1.1> + -Dconfig=$<CONFIGURATION> + -Dtest_imported_debug=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES> + -Dtest_imported_release=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES> + -Dtest_imported_relwithdebinfo=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES> + -Dtest_imported_minsizerel=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES> + -Dtest_alias_file_exe=$<STREQUAL:$<TARGET_FILE:Alias::SomeExe>,$<TARGET_FILE:someexe>> + -Dtest_alias_file_lib=$<STREQUAL:$<TARGET_FILE:Alias::SomeLib>,$<TARGET_FILE:empty1>> + -Dtest_alias_target_name=$<STREQUAL:$<TARGET_PROPERTY:Alias::SomeLib,NAME>,$<TARGET_PROPERTY:empty1,NAME>> + -Dtest_early_termination_1=$<$<1:>: + -Dtest_early_termination_2=$<$<1:>:, + -P ${CMAKE_CURRENT_SOURCE_DIR}/check-part3.cmake + COMMAND ${CMAKE_COMMAND} -E echo "check done (part 3 of 3)" VERBATIM ) diff --git a/Tests/GeneratorExpression/check-part2.cmake b/Tests/GeneratorExpression/check-part2.cmake index 3f7187ca2..a1db5f63d 100644 --- a/Tests/GeneratorExpression/check-part2.cmake +++ b/Tests/GeneratorExpression/check-part2.cmake @@ -34,3 +34,13 @@ check(test_target_includes5 "/empty2/public;/empty3/public;/empty2/public;/empty check(test_target_includes6 "/empty3/public;/empty3/private;/empty2/public;/empty3/public;/empty4/public") check(test_target_includes7 "/empty1/public;/empty2/public;/empty3/public;/empty4/public") check(test_target_includes8 "/empty5/private1;/empty5/private2") +check(test_arbitrary_content_comma_1 "a,") +check(test_arbitrary_content_comma_2 ",a") +check(test_arbitrary_content_comma_3 "a,,") +check(test_arbitrary_content_comma_4 ",") +check(test_arbitrary_content_comma_5 ",,") +check(test_arbitrary_content_comma_6 ",,,") +check(test_arbitrary_content_comma_7 ",,a") +check(test_arbitrary_content_comma_8 "a,,b") +check(test_arbitrary_content_comma_9 "a,,b,,") +check(test_arbitrary_content_comma_10 ",,a,,b,,") diff --git a/Tests/GeneratorExpression/check-part3.cmake b/Tests/GeneratorExpression/check-part3.cmake new file mode 100644 index 000000000..74a596c3a --- /dev/null +++ b/Tests/GeneratorExpression/check-part3.cmake @@ -0,0 +1,28 @@ + +include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake) + +check(test_version_greater_1 "0") +check(test_version_greater_2 "1") +check(test_version_less_1 "0") +check(test_version_less_2 "1") +check(test_version_equal_1 "0") +check(test_version_equal_2 "1") + +foreach(c debug release relwithdebinfo minsizerel) + if(config AND NOT config STREQUAL NoConfig) + if(NOT "${test_imported_${c}}" MATCHES "^;/imported2/include$" + AND NOT "${test_imported_${c}}" MATCHES "^/imported1/include;$") + message(SEND_ERROR "test_imported_${c} is not correct: ${test_imported_${c}}") + endif() + else() + if(NOT "${test_imported_${c}}" MATCHES "^;$") + message(SEND_ERROR "test_imported_${c} is not an empty list: ${test_imported_${c}}") + endif() + endif() +endforeach() + +check(test_alias_file_exe "1") +check(test_alias_file_lib "1") +check(test_alias_target_name "1") +check(test_early_termination_1 "$<:") +check(test_early_termination_2 "$<:,") diff --git a/Tests/GeneratorExpression/empty.cpp b/Tests/GeneratorExpression/empty.cpp index c5399014f..f8732a4aa 100644 --- a/Tests/GeneratorExpression/empty.cpp +++ b/Tests/GeneratorExpression/empty.cpp @@ -1,2 +1,4 @@ - -// empty +#ifdef _WIN32 +__declspec(dllexport) +#endif +int main() { return 0; } diff --git a/Tests/IncludeDirectories/CMP0021/CMakeLists.txt b/Tests/IncludeDirectories/CMP0021/CMakeLists.txt new file mode 100644 index 000000000..0b9aee899 --- /dev/null +++ b/Tests/IncludeDirectories/CMP0021/CMakeLists.txt @@ -0,0 +1,14 @@ + +cmake_policy(SET CMP0021 OLD) +add_executable(cmp0021exe main.cpp) + +if(NOT CMAKE_CURRENT_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/includes") + execute_process(COMMAND ${CMAKE_COMMAND} -E + copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/includes" + "${CMAKE_CURRENT_BINARY_DIR}/includes" + ) +endif() +set_property(TARGET cmp0021exe PROPERTY + INCLUDE_DIRECTORIES includes/cmp0021) diff --git a/Tests/IncludeDirectories/CMP0021/includes/cmp0021/cmp0021.h b/Tests/IncludeDirectories/CMP0021/includes/cmp0021/cmp0021.h new file mode 100644 index 000000000..3d49b31d5 --- /dev/null +++ b/Tests/IncludeDirectories/CMP0021/includes/cmp0021/cmp0021.h @@ -0,0 +1,2 @@ + +#define CMP0021_DEFINE diff --git a/Tests/IncludeDirectories/CMP0021/main.cpp b/Tests/IncludeDirectories/CMP0021/main.cpp new file mode 100644 index 000000000..f886c4629 --- /dev/null +++ b/Tests/IncludeDirectories/CMP0021/main.cpp @@ -0,0 +1,11 @@ + +#include "cmp0021.h" + +#ifndef CMP0021_DEFINE +#error Expected CMP0021_DEFINE +#endif + +int main(int, char **) +{ + return 0; +} diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt index 3e3ecc90d..35ad8dc90 100644 --- a/Tests/IncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/CMakeLists.txt @@ -1,6 +1,23 @@ cmake_minimum_required (VERSION 2.6) project(IncludeDirectories) +if (((CMAKE_C_COMPILER_ID STREQUAL GNU AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.4) + OR CMAKE_C_COMPILER_ID STREQUAL Clang) + AND (CMAKE_GENERATOR STREQUAL "Unix Makefiles" OR CMAKE_GENERATOR STREQUAL "Ninja")) + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag(-Wunused-variable run_sys_includes_test) + if(run_sys_includes_test) + # The Bullseye wrapper appears to break the -isystem effect. + execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE out ERROR_VARIABLE out) + if("x${out}" MATCHES "Bullseye") + set(run_sys_includes_test 0) + endif() + endif() + if (run_sys_includes_test) + add_subdirectory(SystemIncludeDirectories) + endif() +endif() + file(WRITE ${CMAKE_BINARY_DIR}/Flags/Flags.h "//Flags.h ") @@ -69,3 +86,7 @@ get_target_property(incs empty_entry_test INCLUDE_DIRECTORIES) if (NOT incs STREQUAL ";/one/two") message(SEND_ERROR "Empty include_directories entry was not ignored.") endif() + +if(NOT CMAKE_GENERATOR STREQUAL Xcode AND NOT CMAKE_GENERATOR STREQUAL Ninja) + add_subdirectory(CMP0021) +endif() diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt new file mode 100644 index 000000000..aec6ff981 --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt @@ -0,0 +1,19 @@ + +cmake_minimum_required(VERSION 2.8) + +project(SystemIncludeDirectories) + +add_library(systemlib systemlib.cpp) +target_include_directories(systemlib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/systemlib") + +add_library(upstream upstream.cpp) +target_link_libraries(upstream LINK_PUBLIC systemlib) +target_compile_options(upstream PRIVATE -Werror=unused-variable) + +target_include_directories(upstream SYSTEM PUBLIC + $<TARGET_PROPERTY:systemlib,INTERFACE_INCLUDE_DIRECTORIES> +) + +add_library(consumer consumer.cpp) +target_link_libraries(consumer upstream) +target_compile_options(consumer PRIVATE -Werror=unused-variable) diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp b/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp new file mode 100644 index 000000000..197dae86d --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp @@ -0,0 +1,7 @@ + +#include "upstream.h" + +int consumer() +{ + return upstream(); +} diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib.cpp b/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib.cpp new file mode 100644 index 000000000..f111bfa55 --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib.cpp @@ -0,0 +1,4 @@ + +#include "systemlib.h" + +int systemlib() { return 0; } diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib/systemlib.h b/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib/systemlib.h new file mode 100644 index 000000000..c84de6a28 --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/systemlib/systemlib.h @@ -0,0 +1,19 @@ + +#ifndef SYSTEMLIB_H +#define SYSTEMLIB_H + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int systemlib(); + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int unusedFunc() +{ + int unused; + return systemlib(); +} + +#endif diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.cpp b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.cpp new file mode 100644 index 000000000..f716b99e6 --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.cpp @@ -0,0 +1,4 @@ + +#include "upstream.h" + +int upstream() { return systemlib(); } diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h new file mode 100644 index 000000000..3628568cf --- /dev/null +++ b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h @@ -0,0 +1,12 @@ + +#ifndef UPSTREAM_H +#define UPSTREAM_H + +#include "systemlib.h" + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int upstream(); + +#endif diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt index 4a5aa30bb..8e2bd0a0d 100644 --- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt @@ -147,3 +147,24 @@ target_link_libraries(lib5 libbad libgood) target_include_directories(lib5 BEFORE PRIVATE $<TARGET_PROPERTY:libgood,INTERFACE_INCLUDE_DIRECTORIES> ) + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_bat") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_bat/prefix_foo_bar_bat.h" "// prefix_foo_bar_bat.h\n") + +target_include_directories(TargetIncludeDirectories PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/prefix_$<JOIN:foo;bar;bat,/prefix_>") + +# Test that the language generator expressions work +set_property(TARGET TargetIncludeDirectories + APPEND PROPERTY INCLUDE_DIRECTORIES + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>:${CMAKE_CURRENT_BINARY_DIR}/bad>" + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:${CMAKE_CURRENT_BINARY_DIR}/good>" + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:${CMAKE_CURRENT_BINARY_DIR}/othergood/>" +) + +add_executable(TargetIncludeDirectories_C main.c) +set_property(TARGET TargetIncludeDirectories_C + APPEND PROPERTY INCLUDE_DIRECTORIES + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:${CMAKE_CURRENT_BINARY_DIR}/bad>" + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>:${CMAKE_CURRENT_BINARY_DIR}/good>" + "$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>:${CMAKE_CURRENT_BINARY_DIR}/othergood/>" +) diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/main.c b/Tests/IncludeDirectories/TargetIncludeDirectories/main.c new file mode 100644 index 000000000..a597daad0 --- /dev/null +++ b/Tests/IncludeDirectories/TargetIncludeDirectories/main.c @@ -0,0 +1,7 @@ + +#include "common.h" + +int main(void) +{ + return 0; +} diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp b/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp index 90909d334..aed0bde46 100644 --- a/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp +++ b/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp @@ -10,6 +10,8 @@ #include "arguments.h" #include "list.h" #include "target.h" +#include "prefix_foo_bar_bat.h" +#include "common.h" int main(int, char**) { diff --git a/Tests/InterfaceLinkLibraries/CMakeLists.txt b/Tests/InterfaceLinkLibraries/CMakeLists.txt new file mode 100644 index 000000000..bd0cf748e --- /dev/null +++ b/Tests/InterfaceLinkLibraries/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required (VERSION 2.8) + +cmake_policy(SET CMP0022 NEW) + +project(InterfaceLinkLibraries) + +add_library(foo_shared SHARED foo_vs6_1.cpp) +target_compile_definitions(foo_shared INTERFACE FOO_LIBRARY) +add_library(bar_shared SHARED bar_vs6_1.cpp) +target_compile_definitions(bar_shared INTERFACE BAR_LIBRARY) +set_property(TARGET bar_shared APPEND PROPERTY INTERFACE_LINK_LIBRARIES foo_shared) + +add_executable(shared_test main_vs6_1.cpp) +set_property(TARGET shared_test APPEND PROPERTY LINK_LIBRARIES bar_shared) + +add_library(foo_static STATIC foo_vs6_2.cpp) +target_compile_definitions(foo_static INTERFACE FOO_LIBRARY) +add_library(bar_static STATIC bar_vs6_2.cpp) +target_compile_definitions(bar_static INTERFACE BAR_LIBRARY) +set_property(TARGET bar_static APPEND PROPERTY INTERFACE_LINK_LIBRARIES foo_static) + +add_executable(static_test main_vs6_2.cpp) +set_property(TARGET static_test APPEND PROPERTY LINK_LIBRARIES bar_static) + +add_library(foo_shared_private SHARED foo_vs6_3.cpp) +target_compile_definitions(foo_shared_private INTERFACE FOO_LIBRARY) +add_library(bang_shared_private SHARED bang_vs6_1.cpp) +target_compile_definitions(bang_shared_private INTERFACE BANG_LIBRARY) +add_library(bar_shared_private SHARED bar_vs6_3.cpp) +target_compile_definitions(bar_shared_private INTERFACE BAR_LIBRARY) +target_compile_definitions(bar_shared_private PRIVATE BAR_USE_BANG) +set_property(TARGET bar_shared_private APPEND PROPERTY LINK_LIBRARIES bang_shared_private) +set_property(TARGET bar_shared_private APPEND PROPERTY INTERFACE_LINK_LIBRARIES foo_shared_private) + +add_executable(shared_private_test main_vs6_3.cpp) +set_property(TARGET shared_private_test APPEND PROPERTY LINK_LIBRARIES bar_shared_private) + +add_library(foo_static_private STATIC foo_vs6_4.cpp) +target_compile_definitions(foo_static_private INTERFACE FOO_LIBRARY) +add_library(bang_static_private STATIC bang_vs6_2.cpp) +target_compile_definitions(bang_static_private INTERFACE BANG_LIBRARY) +add_library(bar_static_private STATIC bar_vs6_4.cpp) +target_compile_definitions(bar_static_private INTERFACE BAR_LIBRARY) +target_compile_definitions(bar_static_private PRIVATE BAR_USE_BANG) +set_property(TARGET bar_static_private APPEND PROPERTY LINK_LIBRARIES bang_static_private) +set_property(TARGET bar_static_private APPEND PROPERTY INTERFACE_LINK_LIBRARIES $<LINK_ONLY:bang_static_private> foo_static_private) + +add_executable(InterfaceLinkLibraries main_vs6_4.cpp) +set_property(TARGET InterfaceLinkLibraries APPEND PROPERTY LINK_LIBRARIES bar_static_private) diff --git a/Tests/InterfaceLinkLibraries/bang.cpp b/Tests/InterfaceLinkLibraries/bang.cpp new file mode 100644 index 000000000..2e950986b --- /dev/null +++ b/Tests/InterfaceLinkLibraries/bang.cpp @@ -0,0 +1,15 @@ + +#ifdef FOO_LIBRARY +#error Unexpected FOO_LIBRARY +#endif + +#ifdef BAR_LIBRARY +#error Unexpected BAR_LIBRARY +#endif + +#include "bang.h" + +int bang() +{ + return 0; +} diff --git a/Tests/InterfaceLinkLibraries/bang.h b/Tests/InterfaceLinkLibraries/bang.h new file mode 100644 index 000000000..acffb39d9 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/bang.h @@ -0,0 +1,4 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int bang(); diff --git a/Tests/InterfaceLinkLibraries/bang_vs6_1.cpp b/Tests/InterfaceLinkLibraries/bang_vs6_1.cpp new file mode 100644 index 000000000..488686144 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/bang_vs6_1.cpp @@ -0,0 +1 @@ +#include "bang.cpp" diff --git a/Tests/InterfaceLinkLibraries/bang_vs6_2.cpp b/Tests/InterfaceLinkLibraries/bang_vs6_2.cpp new file mode 100644 index 000000000..488686144 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/bang_vs6_2.cpp @@ -0,0 +1 @@ +#include "bang.cpp" diff --git a/Tests/InterfaceLinkLibraries/bar.cpp b/Tests/InterfaceLinkLibraries/bar.cpp new file mode 100644 index 000000000..f39bfa55e --- /dev/null +++ b/Tests/InterfaceLinkLibraries/bar.cpp @@ -0,0 +1,26 @@ + +#ifdef FOO_LIBRARY +#error Unexpected FOO_LIBRARY +#endif + +#ifdef BAR_USE_BANG +# ifndef BANG_LIBRARY +# error Expected BANG_LIBRARY +# endif +# include "bang.h" +#else +# ifdef BANG_LIBRARY +# error Unexpected BANG_LIBRARY +# endif +#endif + +#include "bar.h" + +int bar() +{ +#ifdef BAR_USE_BANG + return bang(); +#else + return 0; +#endif +} diff --git a/Tests/InterfaceLinkLibraries/bar.h b/Tests/InterfaceLinkLibraries/bar.h new file mode 100644 index 000000000..f83b37e57 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/bar.h @@ -0,0 +1,7 @@ + +#include "foo.h" + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int bar(); diff --git a/Tests/InterfaceLinkLibraries/bar_vs6_1.cpp b/Tests/InterfaceLinkLibraries/bar_vs6_1.cpp new file mode 100644 index 000000000..58a04c402 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/bar_vs6_1.cpp @@ -0,0 +1 @@ +#include "bar.cpp" diff --git a/Tests/InterfaceLinkLibraries/bar_vs6_2.cpp b/Tests/InterfaceLinkLibraries/bar_vs6_2.cpp new file mode 100644 index 000000000..58a04c402 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/bar_vs6_2.cpp @@ -0,0 +1 @@ +#include "bar.cpp" diff --git a/Tests/InterfaceLinkLibraries/bar_vs6_3.cpp b/Tests/InterfaceLinkLibraries/bar_vs6_3.cpp new file mode 100644 index 000000000..58a04c402 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/bar_vs6_3.cpp @@ -0,0 +1 @@ +#include "bar.cpp" diff --git a/Tests/InterfaceLinkLibraries/bar_vs6_4.cpp b/Tests/InterfaceLinkLibraries/bar_vs6_4.cpp new file mode 100644 index 000000000..58a04c402 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/bar_vs6_4.cpp @@ -0,0 +1 @@ +#include "bar.cpp" diff --git a/Tests/InterfaceLinkLibraries/foo.cpp b/Tests/InterfaceLinkLibraries/foo.cpp new file mode 100644 index 000000000..5295707b5 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/foo.cpp @@ -0,0 +1,15 @@ + +#ifdef BAR_LIBRARY +#error Unexpected BAR_LIBRARY +#endif + +#ifdef BANG_LIBRARY +#error Unexpected BANG_LIBRARY +#endif + +#include "foo.h" + +int foo() +{ + return 0; +} diff --git a/Tests/InterfaceLinkLibraries/foo.h b/Tests/InterfaceLinkLibraries/foo.h new file mode 100644 index 000000000..e12e23c49 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/foo.h @@ -0,0 +1,4 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int foo(); diff --git a/Tests/InterfaceLinkLibraries/foo_vs6_1.cpp b/Tests/InterfaceLinkLibraries/foo_vs6_1.cpp new file mode 100644 index 000000000..d2e5e52be --- /dev/null +++ b/Tests/InterfaceLinkLibraries/foo_vs6_1.cpp @@ -0,0 +1 @@ +#include "foo.cpp" diff --git a/Tests/InterfaceLinkLibraries/foo_vs6_2.cpp b/Tests/InterfaceLinkLibraries/foo_vs6_2.cpp new file mode 100644 index 000000000..d2e5e52be --- /dev/null +++ b/Tests/InterfaceLinkLibraries/foo_vs6_2.cpp @@ -0,0 +1 @@ +#include "foo.cpp" diff --git a/Tests/InterfaceLinkLibraries/foo_vs6_3.cpp b/Tests/InterfaceLinkLibraries/foo_vs6_3.cpp new file mode 100644 index 000000000..d2e5e52be --- /dev/null +++ b/Tests/InterfaceLinkLibraries/foo_vs6_3.cpp @@ -0,0 +1 @@ +#include "foo.cpp" diff --git a/Tests/InterfaceLinkLibraries/foo_vs6_4.cpp b/Tests/InterfaceLinkLibraries/foo_vs6_4.cpp new file mode 100644 index 000000000..d2e5e52be --- /dev/null +++ b/Tests/InterfaceLinkLibraries/foo_vs6_4.cpp @@ -0,0 +1 @@ +#include "foo.cpp" diff --git a/Tests/InterfaceLinkLibraries/main.cpp b/Tests/InterfaceLinkLibraries/main.cpp new file mode 100644 index 000000000..a54076a75 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/main.cpp @@ -0,0 +1,19 @@ + +#ifndef FOO_LIBRARY +#error Expected FOO_LIBRARY +#endif + +#ifndef BAR_LIBRARY +#error Expected BAR_LIBRARY +#endif + +#ifdef BANG_LIBRARY +#error Unexpected BANG_LIBRARY +#endif + +#include "bar.h" + +int main(void) +{ + return foo() + bar(); +} diff --git a/Tests/InterfaceLinkLibraries/main_vs6_1.cpp b/Tests/InterfaceLinkLibraries/main_vs6_1.cpp new file mode 100644 index 000000000..9b10ef2f8 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/main_vs6_1.cpp @@ -0,0 +1 @@ +#include "main.cpp" diff --git a/Tests/InterfaceLinkLibraries/main_vs6_2.cpp b/Tests/InterfaceLinkLibraries/main_vs6_2.cpp new file mode 100644 index 000000000..9b10ef2f8 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/main_vs6_2.cpp @@ -0,0 +1 @@ +#include "main.cpp" diff --git a/Tests/InterfaceLinkLibraries/main_vs6_3.cpp b/Tests/InterfaceLinkLibraries/main_vs6_3.cpp new file mode 100644 index 000000000..9b10ef2f8 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/main_vs6_3.cpp @@ -0,0 +1 @@ +#include "main.cpp" diff --git a/Tests/InterfaceLinkLibraries/main_vs6_4.cpp b/Tests/InterfaceLinkLibraries/main_vs6_4.cpp new file mode 100644 index 000000000..9b10ef2f8 --- /dev/null +++ b/Tests/InterfaceLinkLibraries/main_vs6_4.cpp @@ -0,0 +1 @@ +#include "main.cpp" diff --git a/Tests/LinkFlags/CMakeLists.txt b/Tests/LinkFlags/CMakeLists.txt index e06020c25..460703542 100644 --- a/Tests/LinkFlags/CMakeLists.txt +++ b/Tests/LinkFlags/CMakeLists.txt @@ -13,6 +13,9 @@ set_property(TARGET LinkFlags_lib PROPERTY STATIC_LIBRARY_FLAGS ${pre}BADFLAG${o add_library(LinkFlags_dll SHARED LinkFlagsLib.c) set_property(TARGET LinkFlags_dll PROPERTY LINK_FLAGS ${pre}BADFLAG${obj}) +add_library(LinkFlags_mod MODULE LinkFlagsLib.c) +set_property(TARGET LinkFlags_mod PROPERTY LINK_FLAGS ${pre}BADFLAG${obj}) + add_executable(LinkFlags_exe LinkFlagsExe.c) set_property(TARGET LinkFlags_exe PROPERTY LINK_FLAGS ${pre}BADFLAG${obj}) @@ -22,7 +25,13 @@ set_property(TARGET LinkFlags_lib_config PROPERTY STATIC_LIBRARY_FLAGS_${TEST_CO add_library(LinkFlags_dll_config SHARED LinkFlagsLib.c) set_property(TARGET LinkFlags_dll_config PROPERTY LINK_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG_${TEST_CONFIG}${obj}) +add_library(LinkFlags_mod_config MODULE LinkFlagsLib.c) +set_property(TARGET LinkFlags_mod_config PROPERTY LINK_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG_${TEST_CONFIG}${obj}) + add_executable(LinkFlags_exe_config LinkFlagsExe.c) set_property(TARGET LinkFlags_exe_config PROPERTY LINK_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG_${TEST_CONFIG}${obj}) add_executable(LinkFlags LinkFlags.c) + +add_subdirectory(LinkerFlags) +add_subdirectory(LinkerFlagsConfig) diff --git a/Tests/LinkFlags/LinkerFlags/CMakeLists.txt b/Tests/LinkFlags/LinkerFlags/CMakeLists.txt new file mode 100644 index 000000000..4707f474c --- /dev/null +++ b/Tests/LinkFlags/LinkerFlags/CMakeLists.txt @@ -0,0 +1,11 @@ +set(CMAKE_STATIC_LINKER_FLAGS ${pre}BADFLAG${obj}) +add_library(LinkFlags_lib_flags STATIC ../LinkFlagsLib.c) + +set(CMAKE_SHARED_LINKER_FLAGS ${pre}BADFLAG${obj}) +add_library(LinkFlags_dll_flags SHARED ../LinkFlagsLib.c) + +set(CMAKE_MODULE_LINKER_FLAGS ${pre}BADFLAG${obj}) +add_library(LinkFlags_mod_flags MODULE ../LinkFlagsLib.c) + +set(CMAKE_EXE_LINKER_FLAGS ${pre}BADFLAG${obj}) +add_executable(LinkFlags_exe_flags ../LinkFlagsExe.c) diff --git a/Tests/LinkFlags/LinkerFlagsConfig/CMakeLists.txt b/Tests/LinkFlags/LinkerFlagsConfig/CMakeLists.txt new file mode 100644 index 000000000..2854fe78b --- /dev/null +++ b/Tests/LinkFlags/LinkerFlagsConfig/CMakeLists.txt @@ -0,0 +1,11 @@ +set(CMAKE_STATIC_LINKER_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG${obj}) +add_library(LinkFlags_lib_flags_config STATIC ../LinkFlagsLib.c) + +set(CMAKE_SHARED_LINKER_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG${obj}) +add_library(LinkFlags_dll_flags_config SHARED ../LinkFlagsLib.c) + +set(CMAKE_MODULE_LINKER_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG${obj}) +add_library(LinkFlags_mod_flags_config MODULE ../LinkFlagsLib.c) + +set(CMAKE_EXE_LINKER_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG${obj}) +add_executable(LinkFlags_exe_flags_config ../LinkFlagsExe.c) diff --git a/Tests/MacRuntimePath/A/CMakeLists.txt b/Tests/MacRuntimePath/A/CMakeLists.txt new file mode 100644 index 000000000..5fc54f406 --- /dev/null +++ b/Tests/MacRuntimePath/A/CMakeLists.txt @@ -0,0 +1,68 @@ +cmake_minimum_required(VERSION 2.8) +project(MacRuntimePath_A) + +# a shared library +add_library(shared SHARED shared.cpp shared.h) +set_target_properties(shared PROPERTIES MACOSX_RPATH 1) + +# a shared library with custom set @rpath +add_library(shared2 SHARED shared.cpp shared.h) +set_target_properties(shared2 PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@rpath") + +# a framework library +add_library(framework SHARED framework.cpp framework.h) +set_target_properties(framework PROPERTIES MACOSX_RPATH 1 FRAMEWORK 1) + +# another framework +add_library(framework2 SHARED framework2.cpp framework2.h) +set_target_properties(framework2 PROPERTIES MACOSX_RPATH 1 FRAMEWORK 1) + +# executable to test a shared library dependency with install rpaths +add_executable(test1 test1.cpp) +target_link_libraries(test1 shared) +set_target_properties(test1 PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 INSTALL_RPATH "@loader_path/../lib") + +# executable to test a framework library dependency with install rpaths +add_executable(test2 test2.cpp) +target_link_libraries(test2 framework) +set_target_properties(test2 PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 INSTALL_RPATH "@loader_path/../lib") + +# executable to test a framework library dependency with build tree rpaths +add_executable(test3 test3.cpp) +target_link_libraries(test3 framework) + +# executable to test a framework library dependency with build tree rpaths +add_executable(test4 test1.cpp) +target_link_libraries(test4 shared2) + +set_target_properties(shared shared2 framework PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") +set_target_properties(test1 test2 test3 test4 PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") +foreach(config ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER ${config} CONFIG) + set_target_properties(shared shared2 framework PROPERTIES + LIBRARY_OUTPUT_DIRECTORY_${CONFIG} + "${CMAKE_CURRENT_BINARY_DIR}/${config}/lib") + set_target_properties(test1 test2 test3 test4 PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_${CONFIG} + "${CMAKE_CURRENT_BINARY_DIR}/${config}/bin") +endforeach() + +foreach(test test1 test2 test3 test4) + add_custom_target(${test}_run ALL + COMMAND ${test} + DEPENDS ${test} + ) +endforeach() + +export(TARGETS shared shared2 framework FILE "${CMAKE_CURRENT_BINARY_DIR}/exp.cmake") + +install(TARGETS shared EXPORT MyExport DESTINATION lib) +install(TARGETS shared2 EXPORT MyExport DESTINATION lib2) +install(TARGETS framework EXPORT MyExport DESTINATION lib-fw) +install(TARGETS framework2 EXPORT MyExport DESTINATION lib-fw2) +install(EXPORT MyExport DESTINATION lib FILE exp.cmake) diff --git a/Tests/MacRuntimePath/A/framework.cpp b/Tests/MacRuntimePath/A/framework.cpp new file mode 100644 index 000000000..abda195ed --- /dev/null +++ b/Tests/MacRuntimePath/A/framework.cpp @@ -0,0 +1,8 @@ + +#include "framework.h" +#include "stdio.h" + +void framework() +{ + printf("framework\n"); +} diff --git a/Tests/MacRuntimePath/A/framework.h b/Tests/MacRuntimePath/A/framework.h new file mode 100644 index 000000000..bdd10f05d --- /dev/null +++ b/Tests/MacRuntimePath/A/framework.h @@ -0,0 +1,17 @@ + +#ifndef framework_h +#define framework_h + +#ifdef WIN32 +# ifdef framework_EXPORTS +# define FRAMEWORK_EXPORT __declspec(dllexport) +# else +# define FRAMEWORK_EXPORT __declspec(dllimport) +# endif +#else +# define FRAMEWORK_EXPORT +#endif + +void FRAMEWORK_EXPORT framework(); + +#endif diff --git a/Tests/MacRuntimePath/A/framework2.cpp b/Tests/MacRuntimePath/A/framework2.cpp new file mode 100644 index 000000000..d3c2c458d --- /dev/null +++ b/Tests/MacRuntimePath/A/framework2.cpp @@ -0,0 +1,8 @@ + +#include "framework2.h" +#include "stdio.h" + +void framework2() +{ + printf("framework 2\n"); +} diff --git a/Tests/MacRuntimePath/A/framework2.h b/Tests/MacRuntimePath/A/framework2.h new file mode 100644 index 000000000..4576d12dc --- /dev/null +++ b/Tests/MacRuntimePath/A/framework2.h @@ -0,0 +1,17 @@ + +#ifndef framework2_h +#define framework2_h + +#ifdef WIN32 +# ifdef framework2_EXPORTS +# define FRAMEWORK2_EXPORT __declspec(dllexport) +# else +# define FRAMEWORK2_EXPORT __declspec(dllimport) +# endif +#else +# define FRAMEWORK2_EXPORT +#endif + +void FRAMEWORK2_EXPORT framework2(); + +#endif diff --git a/Tests/MacRuntimePath/A/shared.cpp b/Tests/MacRuntimePath/A/shared.cpp new file mode 100644 index 000000000..e5e7dc5ae --- /dev/null +++ b/Tests/MacRuntimePath/A/shared.cpp @@ -0,0 +1,8 @@ + +#include "shared.h" +#include "stdio.h" + +void shared() +{ + printf("shared\n"); +} diff --git a/Tests/MacRuntimePath/A/shared.h b/Tests/MacRuntimePath/A/shared.h new file mode 100644 index 000000000..3588fb88e --- /dev/null +++ b/Tests/MacRuntimePath/A/shared.h @@ -0,0 +1,17 @@ + +#ifndef shared_h +#define shared_h + +#ifdef WIN32 +# ifdef shared_EXPORTS +# define SHARED_EXPORT __declspec(dllexport) +# else +# define SHARED_EXPORT __declspec(dllimport) +# endif +#else +# define SHARED_EXPORT +#endif + +void SHARED_EXPORT shared(); + +#endif diff --git a/Tests/MacRuntimePath/A/test1.cpp b/Tests/MacRuntimePath/A/test1.cpp new file mode 100644 index 000000000..cb934488f --- /dev/null +++ b/Tests/MacRuntimePath/A/test1.cpp @@ -0,0 +1,8 @@ + +#include "shared.h" + +int main(int, char**) +{ + shared(); + return 0; +} diff --git a/Tests/MacRuntimePath/A/test2.cpp b/Tests/MacRuntimePath/A/test2.cpp new file mode 100644 index 000000000..26bc9ddf9 --- /dev/null +++ b/Tests/MacRuntimePath/A/test2.cpp @@ -0,0 +1,8 @@ + +#include "framework.h" + +int main(int, char**) +{ + framework(); + return 0; +} diff --git a/Tests/MacRuntimePath/A/test3.cpp b/Tests/MacRuntimePath/A/test3.cpp new file mode 100644 index 000000000..26bc9ddf9 --- /dev/null +++ b/Tests/MacRuntimePath/A/test3.cpp @@ -0,0 +1,8 @@ + +#include "framework.h" + +int main(int, char**) +{ + framework(); + return 0; +} diff --git a/Tests/MacRuntimePath/B/CMakeLists.txt b/Tests/MacRuntimePath/B/CMakeLists.txt new file mode 100644 index 000000000..4317af655 --- /dev/null +++ b/Tests/MacRuntimePath/B/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 2.8) +project(MacRuntimePath_B) + +include(${MacRuntimePath_B_BINARY_DIR}/../Root/lib/exp.cmake) + +add_executable(testb ${MacRuntimePath_B_SOURCE_DIR}/../A/test3.cpp) + +# test link with rpath enabled targets +target_link_libraries(testb shared framework) + +# test link with rpath enabled library by filename +find_library(fw2 NAMES framework2 HINTS ${MacRuntimePath_B_BINARY_DIR}/../Root/lib-fw2) +target_link_libraries(testb $<TARGET_LINKER_FILE:shared2> ${fw2}) + +add_custom_target(testb_run ALL + COMMAND testb + DEPENDS testb + ) diff --git a/Tests/MacRuntimePath/CMakeLists.txt b/Tests/MacRuntimePath/CMakeLists.txt new file mode 100644 index 000000000..5e5b6c421 --- /dev/null +++ b/Tests/MacRuntimePath/CMakeLists.txt @@ -0,0 +1,72 @@ +cmake_minimum_required (VERSION 2.8) +project(MacRuntimePath) + + +# Wipe out the install tree to make sure the exporter works. +add_custom_command( + OUTPUT ${MacRuntimePath_BINARY_DIR}/CleanupProject + COMMAND ${CMAKE_COMMAND} -E remove_directory ${MacRuntimePath_BINARY_DIR}/Root + ) +add_custom_target(CleanupTarget ALL DEPENDS ${MacRuntimePath_BINARY_DIR}/CleanupProject) +set_property( + SOURCE ${MacRuntimePath_BINARY_DIR}/CleanupProject + PROPERTY SYMBOLIC 1 + ) + +configure_file(${MacRuntimePath_SOURCE_DIR}/InitialCache.cmake.in + ${MacRuntimePath_BINARY_DIR}/InitialCache.cmake @ONLY) + +if(CMAKE_CONFIGURATION_TYPES) + set(NESTED_CONFIG_TYPE -C "${CMAKE_CFG_INTDIR}") +else() + if(CMAKE_BUILD_TYPE) + set(NESTED_CONFIG_TYPE -C "${CMAKE_BUILD_TYPE}") + else() + set(NESTED_CONFIG_TYPE) + endif() +endif() + +# Build and install the exporter. +add_custom_command( + OUTPUT ${MacRuntimePath_BINARY_DIR}/ExportProject + COMMAND ${CMAKE_CTEST_COMMAND} ${NESTED_CONFIG_TYPE} + --build-and-test + ${MacRuntimePath_SOURCE_DIR}/A + ${MacRuntimePath_BINARY_DIR}/A + --build-noclean + --build-project MacRuntimePath_A + --build-target install + --build-generator ${CMAKE_GENERATOR} + --build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}" + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-options -C${MacRuntimePath_BINARY_DIR}/InitialCache.cmake + VERBATIM + ) +add_custom_target(ExportTarget ALL DEPENDS ${MacRuntimePath_BINARY_DIR}/ExportProject) +add_dependencies(ExportTarget CleanupTarget) +set_property( + SOURCE ${MacRuntimePath_BINARY_DIR}/ExportProject + PROPERTY SYMBOLIC 1 + ) + +# Build the importer. +add_custom_command( + OUTPUT ${MacRuntimePath_BINARY_DIR}/ImportProject + COMMAND ${CMAKE_CTEST_COMMAND} ${NESTED_CONFIG_TYPE} + --build-and-test + ${MacRuntimePath_SOURCE_DIR}/B + ${MacRuntimePath_BINARY_DIR}/B + --build-noclean + --build-project MacRuntimePath_B + --build-generator ${CMAKE_GENERATOR} + --build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}" + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-options -C${MacRuntimePath_BINARY_DIR}/InitialCache.cmake + VERBATIM + ) +add_custom_target(ImportTarget ALL DEPENDS ${MacRuntimePath_BINARY_DIR}/ImportProject) +add_dependencies(ImportTarget ExportTarget) +set_property( + SOURCE ${MacRuntimePath_BINARY_DIR}/ImportProject + PROPERTY SYMBOLIC 1 + ) diff --git a/Tests/MacRuntimePath/InitialCache.cmake.in b/Tests/MacRuntimePath/InitialCache.cmake.in new file mode 100644 index 000000000..be15eb30b --- /dev/null +++ b/Tests/MacRuntimePath/InitialCache.cmake.in @@ -0,0 +1,13 @@ +set(CMAKE_C_COMPILER "@CMAKE_C_COMPILER@" CACHE STRING "C Compiler") +set(CMAKE_C_FLAGS "@CMAKE_C_FLAGS@" CACHE STRING "C Flags") +set(CMAKE_C_FLAGS_DEBUG "@CMAKE_C_FLAGS_DEBUG@" CACHE STRING "C Flags") +set(CMAKE_C_FLAGS_RELEASE "@CMAKE_C_FLAGS_RELEASE@" CACHE STRING "C Flags") +set(CMAKE_C_FLAGS_MINSIZEREL "@CMAKE_C_FLAGS_MINSIZEREL@" CACHE STRING "C Flags") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "@CMAKE_C_FLAGS_RELWITHDEBINFO@" CACHE STRING "C Flags") +set(CMAKE_CXX_COMPILER "@CMAKE_CXX_COMPILER@" CACHE STRING "C++ Compiler") +set(CMAKE_CXX_FLAGS "@CMAKE_CXX_FLAGS@" CACHE STRING "C++ Flags") +set(CMAKE_CXX_FLAGS_DEBUG "@CMAKE_CXX_FLAGS_DEBUG@" CACHE STRING "C++ Flags") +set(CMAKE_CXX_FLAGS_RELEASE "@CMAKE_CXX_FLAGS_RELEASE@" CACHE STRING "C++ Flags") +set(CMAKE_CXX_FLAGS_MINSIZEREL "@CMAKE_CXX_FLAGS_MINSIZEREL@" CACHE STRING "C++ Flags") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "@CMAKE_CXX_FLAGS_RELWITHDEBINFO@" CACHE STRING "C++ Flags") +set(CMAKE_INSTALL_PREFIX "@MacRuntimePath_BINARY_DIR@/Root" CACHE STRING "Installation Prefix") diff --git a/Tests/Module/GenerateExportHeader/CMakeLists.txt b/Tests/Module/GenerateExportHeader/CMakeLists.txt index 4a5b1cb5a..09f188191 100644 --- a/Tests/Module/GenerateExportHeader/CMakeLists.txt +++ b/Tests/Module/GenerateExportHeader/CMakeLists.txt @@ -23,13 +23,13 @@ set( CMAKE_INCLUDE_CURRENT_DIR ON ) macro(TEST_FAIL value msg) if (${value}) - message (SEND_ERROR "Test fail:" ${msg} ${Out} ) + message (SEND_ERROR "Test fail:" "${msg}\n" ${Out} ) endif () endmacro() macro(TEST_PASS value msg) if (NOT ${value}) - message (SEND_ERROR "Test fail:" ${msg} ${Out} ) + message (SEND_ERROR "Test fail:" "${msg}\n" ${Out} ) endif () endmacro() @@ -141,6 +141,8 @@ endmacro() include(GenerateExportHeader) +add_subdirectory(visibility_preset) + add_compiler_export_flags() set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) @@ -168,6 +170,9 @@ add_subdirectory(lib_shared_and_statictest) add_subdirectory(override_symbol) add_subdirectory(nodeprecated) add_subdirectory(prefix) +if(NOT BORLAND) + add_subdirectory(c_identifier) +endif() if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES Clang)) # We deliberately call deprecated methods, and test for that elsewhere. diff --git a/Tests/Module/GenerateExportHeader/c_identifier/CMakeLists.txt b/Tests/Module/GenerateExportHeader/c_identifier/CMakeLists.txt new file mode 100644 index 000000000..9f8c8efe6 --- /dev/null +++ b/Tests/Module/GenerateExportHeader/c_identifier/CMakeLists.txt @@ -0,0 +1,13 @@ +project(c_identifier) + +set(c_identifier_lib_SRCS + c_identifier_class.cpp +) + +add_library(7c-identifier-lib++ SHARED c_identifier_class.cpp) + +generate_export_header(7c-identifier-lib++) + +add_executable(c_identifier_exe main.cpp) + +target_link_libraries(c_identifier_exe 7c-identifier-lib++) diff --git a/Tests/Module/GenerateExportHeader/c_identifier/c_identifier_class.cpp b/Tests/Module/GenerateExportHeader/c_identifier/c_identifier_class.cpp new file mode 100644 index 000000000..d252c8e8f --- /dev/null +++ b/Tests/Module/GenerateExportHeader/c_identifier/c_identifier_class.cpp @@ -0,0 +1,7 @@ + +#include "c_identifier_class.h" + +int CIdentifierClass::someMethod() const +{ + return 0; +} diff --git a/Tests/Module/GenerateExportHeader/c_identifier/c_identifier_class.h b/Tests/Module/GenerateExportHeader/c_identifier/c_identifier_class.h new file mode 100644 index 000000000..741efdcec --- /dev/null +++ b/Tests/Module/GenerateExportHeader/c_identifier/c_identifier_class.h @@ -0,0 +1,13 @@ + +#ifndef C_IDENTIFIER_CLASS_H +#define C_IDENTIFIER_CLASS_H + +#include "7c-identifier-lib++_export.h" + +class _7C_IDENTIFIER_LIB___EXPORT CIdentifierClass +{ +public: + int someMethod() const; +}; + +#endif diff --git a/Tests/Module/GenerateExportHeader/c_identifier/main.cpp b/Tests/Module/GenerateExportHeader/c_identifier/main.cpp new file mode 100644 index 000000000..68beebb8f --- /dev/null +++ b/Tests/Module/GenerateExportHeader/c_identifier/main.cpp @@ -0,0 +1,8 @@ + +#include "c_identifier_class.h" + +int main(int argc, char **argv) +{ + CIdentifierClass cic; + return cic.someMethod(); +} diff --git a/Tests/Module/GenerateExportHeader/libsharedtest/CMakeLists.txt b/Tests/Module/GenerateExportHeader/libsharedtest/CMakeLists.txt index a5804fcfb..2a97d8f83 100644 --- a/Tests/Module/GenerateExportHeader/libsharedtest/CMakeLists.txt +++ b/Tests/Module/GenerateExportHeader/libsharedtest/CMakeLists.txt @@ -8,6 +8,7 @@ macro(shared_build_fail Source Message) endmacro() shared_build_pass("Libshared l; return l.libshared_exported();" "Failed to build exported") +shared_build_pass("return libshared_exported();" "Failed to build exported function.") # if (COMPILER_HAS_DEPRECATED) # shared_build_fail("Libshared l; return l.libshared_deprecated();" "Built use of deprecated class method. This should not be possible.") diff --git a/Tests/Module/GenerateExportHeader/visibility_preset/CMakeLists.txt b/Tests/Module/GenerateExportHeader/visibility_preset/CMakeLists.txt new file mode 100644 index 000000000..2571d2224 --- /dev/null +++ b/Tests/Module/GenerateExportHeader/visibility_preset/CMakeLists.txt @@ -0,0 +1,17 @@ + +set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) + +if (CMAKE_CXX_FLAGS MATCHES "-fvisibility=hidden") + message(SEND_ERROR "Do not use add_compiler_export_flags before adding this directory") +endif() +if (CMAKE_CXX_FLAGS MATCHES "-fvisibility-inlines-hidden") + message(SEND_ERROR "Do not use add_compiler_export_flags before adding this directory") +endif() + +add_library(visibility_preset SHARED visibility_preset.cpp) +generate_export_header(visibility_preset) + +add_executable(visibility_preset_exe main.cpp) + +target_link_libraries(visibility_preset_exe visibility_preset) diff --git a/Tests/Module/GenerateExportHeader/visibility_preset/main.cpp b/Tests/Module/GenerateExportHeader/visibility_preset/main.cpp new file mode 100644 index 000000000..89c397784 --- /dev/null +++ b/Tests/Module/GenerateExportHeader/visibility_preset/main.cpp @@ -0,0 +1,9 @@ + +#include "visibility_preset.h" + +int main() +{ + VisibilityPreset vp; + vp.someMethod(); + return 0; +} diff --git a/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.cpp b/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.cpp new file mode 100644 index 000000000..c97dec6e2 --- /dev/null +++ b/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.cpp @@ -0,0 +1,7 @@ + +#include "visibility_preset.h" + +void VisibilityPreset::someMethod() +{ + +} diff --git a/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.h b/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.h new file mode 100644 index 000000000..8becbe189 --- /dev/null +++ b/Tests/Module/GenerateExportHeader/visibility_preset/visibility_preset.h @@ -0,0 +1,13 @@ + +#ifndef VISIBILITY_PRESET_H +#define VISIBILITY_PRESET_H + +#include "visibility_preset_export.h" + +class VISIBILITY_PRESET_EXPORT VisibilityPreset +{ +public: + void someMethod(); +}; + +#endif diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt index bc2f01317..28e46b1f5 100644 --- a/Tests/PDBDirectoryAndName/CMakeLists.txt +++ b/Tests/PDBDirectoryAndName/CMakeLists.txt @@ -20,7 +20,9 @@ set_target_properties(mylibB PROPERTIES PDB_NAME "mylibB_Special" PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB" ) -list(APPEND my_targets mylibB) +# TODO: The only .pdb available for a static library is that generated +# by the compiler /Fd option which is not the same as the linker /pdb. +# list(APPEND my_targets mylibB) add_library(mylibC SHARED mylibC.c) set_target_properties(mylibC PROPERTIES @@ -32,7 +34,8 @@ add_library(mylibD STATIC mylibD.c) set_target_properties(mylibD PROPERTIES PDB_NAME "mylibD_Special" ) -list(APPEND my_targets mylibD) +# TODO: See comment for mylibB. +# list(APPEND my_targets mylibD) add_executable(myexe myexe.c) set_target_properties(myexe PROPERTIES @@ -58,10 +61,6 @@ target_link_libraries(myexe2 mylibA mylibD) if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6") return() endif() -# PDB output not fully implemented for Intel -if("${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$") - return() -endif() set(pdbs "") foreach(t ${my_targets}) diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt index ad119cc68..d44cb9c82 100644 --- a/Tests/Preprocess/CMakeLists.txt +++ b/Tests/Preprocess/CMakeLists.txt @@ -58,8 +58,7 @@ endif() # must not have it escaped inside the configured header. set(STRING_EXTRA "") -if(NOT BORLAND AND NOT PP_VS70 - AND NOT PP_VS100 AND NOT PP_VS110 AND NOT PP_VS120) +if(NOT BORLAND AND NOT PP_VS70) # Borland, VS70 IDE: ; # The Borland compiler will simply not accept a non-escaped semicolon # on the command line. If it is escaped \; then the escape character @@ -67,7 +66,6 @@ if(NOT BORLAND AND NOT PP_VS70 # # The VS 7.0 IDE separates definitions on semicolons and commas with # no regard for quotes. Fortunately VS 7.1 and above are okay. - # VS 10 seems to also not like semicolons set(SEMICOLON "\;") endif() @@ -261,6 +259,19 @@ set_property( ${DEF_FILE_PATH} ) +# Try reading and writing the property value to ensure the string is +# preserved. +get_property(defs1 TARGET Preprocess PROPERTY COMPILE_DEFINITIONS) +set_property(TARGET Preprocess PROPERTY COMPILE_DEFINITIONS "${defs1}") +get_property(defs2 TARGET Preprocess PROPERTY COMPILE_DEFINITIONS) +if(NOT "x${defs1}" STREQUAL "x${defs2}") + message(FATAL_ERROR "get/set/get COMPILE_DEFINITIONS round trip failed. " + "First get:\n" + " ${defs1}\n" + "Second get:\n" + " ${defs2}") +endif() + # Helper target for running test manually in build tree. add_custom_target(drive COMMAND Preprocess) diff --git a/Tests/Qt4And5Automoc/CMakeLists.txt b/Tests/Qt4And5Automoc/CMakeLists.txt new file mode 100644 index 000000000..0cc80fe73 --- /dev/null +++ b/Tests/Qt4And5Automoc/CMakeLists.txt @@ -0,0 +1,13 @@ + +project(Qt4And5Automoc) + +find_package(Qt4 REQUIRED) +find_package(Qt5Core REQUIRED) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +add_executable(qt4_exe main_qt4.cpp) +target_link_libraries(qt4_exe Qt4::QtCore) +add_executable(qt5_exe main_qt5.cpp) +target_link_libraries(qt5_exe Qt5::Core) diff --git a/Tests/Qt4And5Automoc/main.cpp b/Tests/Qt4And5Automoc/main.cpp new file mode 100644 index 000000000..00fd64153 --- /dev/null +++ b/Tests/Qt4And5Automoc/main.cpp @@ -0,0 +1,18 @@ + +#include <QObject> + +class SomeObject : public QObject +{ + Q_OBJECT +public: + explicit SomeObject(QObject *parent = 0) + : QObject(parent) + { + + } +}; + +int main(int argc, char **argv) +{ + return 0; +} diff --git a/Tests/Qt4And5Automoc/main_qt4.cpp b/Tests/Qt4And5Automoc/main_qt4.cpp new file mode 100644 index 000000000..a84ce897f --- /dev/null +++ b/Tests/Qt4And5Automoc/main_qt4.cpp @@ -0,0 +1,4 @@ + +#include "main.cpp" + +#include "main_qt4.moc" diff --git a/Tests/Qt4And5Automoc/main_qt5.cpp b/Tests/Qt4And5Automoc/main_qt5.cpp new file mode 100644 index 000000000..287b26137 --- /dev/null +++ b/Tests/Qt4And5Automoc/main_qt5.cpp @@ -0,0 +1,4 @@ + +#include "main.cpp" + +#include "main_qt5.moc" diff --git a/Tests/Qt4Targets/CMakeLists.txt b/Tests/Qt4Targets/CMakeLists.txt index d0c9c667a..af9fc3fe7 100644 --- a/Tests/Qt4Targets/CMakeLists.txt +++ b/Tests/Qt4Targets/CMakeLists.txt @@ -19,3 +19,20 @@ if (WIN32) target_link_libraries(activeqtexe Qt4::QAxServer Qt4::QtGui) endif() endif() + +qt4_generate_moc(main_gen_test.cpp + "${CMAKE_CURRENT_BINARY_DIR}/main_gen_test.moc" + TARGET Qt4GenerateMacroTest +) +add_executable(Qt4GenerateMacroTest WIN32 main_gen_test.cpp "${CMAKE_CURRENT_BINARY_DIR}/main_gen_test.moc") +set_property(TARGET Qt4GenerateMacroTest PROPERTY AUTOMOC OFF) +target_include_directories(Qt4GenerateMacroTest PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/interface") +target_link_libraries(Qt4GenerateMacroTest Qt4::QtGui) + +qt4_wrap_cpp(moc_file mywrapobject.h + TARGET Qt4WrapMacroTest +) +add_executable(Qt4WrapMacroTest WIN32 main_wrap_test.cpp ${moc_file}) +set_property(TARGET Qt4WrapMacroTest PROPERTY AUTOMOC OFF) +target_include_directories(Qt4WrapMacroTest PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/interface") +target_link_libraries(Qt4WrapMacroTest Qt4::QtGui) diff --git a/Tests/Qt4Targets/interface/myinterface.h b/Tests/Qt4Targets/interface/myinterface.h new file mode 100644 index 000000000..59b43adf4 --- /dev/null +++ b/Tests/Qt4Targets/interface/myinterface.h @@ -0,0 +1,12 @@ + +#ifndef MYINTERFACE_H +#define MYINTERFACE_H + +class MyInterface +{ + +}; + +Q_DECLARE_INTERFACE(MyInterface, "org.cmake.example.MyInterface") + +#endif diff --git a/Tests/Qt4Targets/main_gen_test.cpp b/Tests/Qt4Targets/main_gen_test.cpp new file mode 100644 index 000000000..984424b1e --- /dev/null +++ b/Tests/Qt4Targets/main_gen_test.cpp @@ -0,0 +1,21 @@ + +#include <QObject> + +#include "myinterface.h" + +class MyObject : public QObject, MyInterface +{ + Q_OBJECT + Q_INTERFACES(MyInterface) +public: + explicit MyObject(QObject *parent = 0) : QObject(parent) { } +}; + +int main(int argc, char **argv) +{ + MyObject mo; + mo.objectName(); + return 0; +} + +#include "main_gen_test.moc" diff --git a/Tests/Qt4Targets/main_wrap_test.cpp b/Tests/Qt4Targets/main_wrap_test.cpp new file mode 100644 index 000000000..21edc7b32 --- /dev/null +++ b/Tests/Qt4Targets/main_wrap_test.cpp @@ -0,0 +1,11 @@ + +#include <QObject> + +#include "mywrapobject.h" + +int main(int argc, char **argv) +{ + MyWrapObject mwo; + mwo.objectName(); + return 0; +} diff --git a/Tests/Qt4Targets/mywrapobject.h b/Tests/Qt4Targets/mywrapobject.h new file mode 100644 index 000000000..de23540a2 --- /dev/null +++ b/Tests/Qt4Targets/mywrapobject.h @@ -0,0 +1,17 @@ + +#ifndef MYWRAPOBJECT_H +#define MYWRAPOBJECT_H + +#include <QObject> + +#include "myinterface.h" + +class MyWrapObject : public QObject, MyInterface +{ + Q_OBJECT + Q_INTERFACES(MyInterface) +public: + explicit MyWrapObject(QObject *parent = 0) : QObject(parent) { } +}; + +#endif diff --git a/Tests/QtAutomoc/Adir/CMakeLists.txt b/Tests/QtAutomoc/Adir/CMakeLists.txt index 171222319..a1c36ffce 100644 --- a/Tests/QtAutomoc/Adir/CMakeLists.txt +++ b/Tests/QtAutomoc/Adir/CMakeLists.txt @@ -4,5 +4,5 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) add_library(libA SHARED libA.cpp) -target_link_libraries(libA LINK_PUBLIC Qt4::QtCore) +target_link_libraries(libA LINK_PUBLIC ${QT_QTCORE_TARGET}) generate_export_header(libA) diff --git a/Tests/QtAutomoc/CMakeLists.txt b/Tests/QtAutomoc/CMakeLists.txt index fd624c803..69e52ac5d 100644 --- a/Tests/QtAutomoc/CMakeLists.txt +++ b/Tests/QtAutomoc/CMakeLists.txt @@ -2,9 +2,31 @@ cmake_minimum_required(VERSION 2.8) project(QtAutomoc) -find_package(Qt4 REQUIRED) +if (QT_TEST_VERSION STREQUAL 4) + find_package(Qt4 REQUIRED) + + # Include this directory before using the UseQt4 file. + add_subdirectory(defines_test) + + include(UseQt4) + + set(QT_QTCORE_TARGET Qt4::QtCore) +else() + if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") + endif() + find_package(Qt5Widgets REQUIRED) + + set(QT_QTCORE_TARGET Qt5::Core) + + include_directories(${Qt5Widgets_INCLUDE_DIRS}) + set(QT_LIBRARIES Qt5::Widgets) + + if(Qt5_POSITION_INDEPENDENT_CODE) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + endif() +endif() -include(UseQt4) include_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/Tests/QtAutomoc/calwidget.cpp b/Tests/QtAutomoc/calwidget.cpp index 24f3b4efe..cbfa5a8a6 100644 --- a/Tests/QtAutomoc/calwidget.cpp +++ b/Tests/QtAutomoc/calwidget.cpp @@ -38,7 +38,14 @@ ** ****************************************************************************/ - #include <QtGui> + #include <QComboBox> + #include <QGridLayout> + #include <QLabel> + #include <QGroupBox> + #include <QCheckBox> + #include <QDateEdit> + #include <QCalendarWidget> + #include <QTextCharFormat> #include "calwidget.h" @@ -414,10 +421,10 @@ QComboBox *Window::createColorComboBox() { QComboBox *comboBox = new QComboBox; - comboBox->addItem(tr("Red"), Qt::red); - comboBox->addItem(tr("Blue"), Qt::blue); - comboBox->addItem(tr("Black"), Qt::black); - comboBox->addItem(tr("Magenta"), Qt::magenta); + comboBox->addItem(tr("Red"), QColor(Qt::red)); + comboBox->addItem(tr("Blue"), QColor(Qt::blue)); + comboBox->addItem(tr("Black"), QColor(Qt::black)); + comboBox->addItem(tr("Magenta"), QColor(Qt::magenta)); return comboBox; } diff --git a/Tests/QtAutomoc/defines_test/CMakeLists.txt b/Tests/QtAutomoc/defines_test/CMakeLists.txt new file mode 100644 index 000000000..ad4e684cb --- /dev/null +++ b/Tests/QtAutomoc/defines_test/CMakeLists.txt @@ -0,0 +1,6 @@ + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +add_executable(defines_test defines_test.cpp) +set_target_properties(defines_test PROPERTIES AUTOMOC TRUE) +target_link_libraries(defines_test Qt4::QtGui) diff --git a/Tests/QtAutomoc/defines_test/defines_test.cpp b/Tests/QtAutomoc/defines_test/defines_test.cpp new file mode 100644 index 000000000..2836d357b --- /dev/null +++ b/Tests/QtAutomoc/defines_test/defines_test.cpp @@ -0,0 +1,38 @@ + +#include <QObject> + +#ifdef QT_GUI_LIB +#include <QTextDocument> + +class SomeDocument : public QTextDocument +{ + Q_OBJECT + +Q_SIGNALS: + void someSig(); +}; +#endif + +#ifdef QT_CORE_LIB +class SomeObject : public QObject +{ + Q_OBJECT + +Q_SIGNALS: + void someSig(); +}; +#endif + +int main(int argc, char **argv) +{ +#ifdef QT_CORE_LIB + QMetaObject sosmo = SomeObject::staticMetaObject; +#endif +#ifdef QT_GUI_LIB + QMetaObject sdsmo = SomeDocument::staticMetaObject; +#endif + + return 0; +} + +#include "defines_test.moc" diff --git a/Tests/QtAutomoc/foo.h b/Tests/QtAutomoc/foo.h index 32d4c8d8f..f23ec0739 100644 --- a/Tests/QtAutomoc/foo.h +++ b/Tests/QtAutomoc/foo.h @@ -16,7 +16,10 @@ #include <QObject> -class Foo : public QObject +class Foo +#ifdef FOO + : public QObject +#endif { Q_OBJECT public: diff --git a/Tests/QtAutomoc/main.cpp b/Tests/QtAutomoc/main.cpp index d952171b5..bd80180bf 100644 --- a/Tests/QtAutomoc/main.cpp +++ b/Tests/QtAutomoc/main.cpp @@ -38,7 +38,7 @@ ** ****************************************************************************/ -#include <QtGui> +#include <QApplication> #include "codeeditor.h" #include "calwidget.h" diff --git a/Tests/ReturnTest/CMakeLists.txt b/Tests/ReturnTest/CMakeLists.txt index 3bd7ce099..c4c606c58 100644 --- a/Tests/ReturnTest/CMakeLists.txt +++ b/Tests/ReturnTest/CMakeLists.txt @@ -140,7 +140,7 @@ endwhile() if ("${iter}" STREQUAL "aaa") pass ("break in a while") else () - failed ("break in a whi;e got: ${whiletestResult}") + failed ("break in a while got: ${whiletestResult}") endif () diff --git a/Tests/RunCMake/CMP0004/CMP0004-NEW.cmake b/Tests/RunCMake/CMP0004/CMP0004-NEW.cmake index 7c61961f5..f42d8e49d 100644 --- a/Tests/RunCMake/CMP0004/CMP0004-NEW.cmake +++ b/Tests/RunCMake/CMP0004/CMP0004-NEW.cmake @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) cmake_policy(SET CMP0004 NEW) diff --git a/Tests/RunCMake/CMP0004/CMP0004-OLD.cmake b/Tests/RunCMake/CMP0004/CMP0004-OLD.cmake index d6ed72c79..3fa58b6b6 100644 --- a/Tests/RunCMake/CMP0004/CMP0004-OLD.cmake +++ b/Tests/RunCMake/CMP0004/CMP0004-OLD.cmake @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) cmake_policy(SET CMP0004 OLD) diff --git a/Tests/RunCMake/CMP0004/CMP0004-policy-genex.cmake b/Tests/RunCMake/CMP0004/CMP0004-policy-genex.cmake index eab680a92..297047662 100644 --- a/Tests/RunCMake/CMP0004/CMP0004-policy-genex.cmake +++ b/Tests/RunCMake/CMP0004/CMP0004-policy-genex.cmake @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) cmake_policy(SET CMP0004 NEW) diff --git a/Tests/RunCMake/CMP0004/CMakeLists.txt b/Tests/RunCMake/CMP0004/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/CMP0004/CMakeLists.txt +++ b/Tests/RunCMake/CMP0004/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0019/CMakeLists.txt b/Tests/RunCMake/CMP0019/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/CMP0019/CMakeLists.txt +++ b/Tests/RunCMake/CMP0019/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0022/CMP0022-NOWARN-exe-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-exe-stderr.txt new file mode 100644 index 000000000..10f32932e --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-exe-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/CMP0022/CMP0022-NOWARN-exe.cmake b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-exe.cmake new file mode 100644 index 000000000..b0268c842 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-exe.cmake @@ -0,0 +1,7 @@ +enable_language(CXX) + +add_library(testLib empty_vs6_1.cpp) +add_executable(testExe empty_vs6_2.cpp) +target_link_libraries(testExe testLib) + +export(TARGETS testExe FILE "${CMAKE_CURRENT_BINARY_DIR}/cmp0022NOWARN-exe.cmake") diff --git a/Tests/RunCMake/CMP0022/CMP0022-NOWARN-shared-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-shared-stderr.txt new file mode 100644 index 000000000..10f32932e --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-shared-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/CMP0022/CMP0022-NOWARN-shared.cmake b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-shared.cmake new file mode 100644 index 000000000..57c3ed0d7 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-shared.cmake @@ -0,0 +1,8 @@ +enable_language(CXX) + +add_library(foo SHARED empty_vs6_1.cpp) +add_library(bar SHARED empty_vs6_2.cpp) +target_link_libraries(bar foo) + +add_executable(zot empty.cpp) +target_link_libraries(zot bar) diff --git a/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-link_libraries-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-link_libraries-stderr.txt new file mode 100644 index 000000000..10f32932e --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-link_libraries-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-link_libraries.cmake b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-link_libraries.cmake new file mode 100644 index 000000000..42c4084a6 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-link_libraries.cmake @@ -0,0 +1,9 @@ + +enable_language(CXX) + +add_subdirectory(dep1) +add_subdirectory(dep2) +add_subdirectory(dep3) + +add_library(somelib empty.cpp) +target_link_libraries(somelib dep3) diff --git a/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-stderr.txt new file mode 100644 index 000000000..10f32932e --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static.cmake b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static.cmake new file mode 100644 index 000000000..ad3b8df74 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-NOWARN-static.cmake @@ -0,0 +1,12 @@ + +project(CMP0022-NOWARN-static) + +add_library(foo STATIC empty_vs6_1.cpp) +add_library(bar STATIC empty_vs6_2.cpp) +add_library(bat STATIC empty_vs6_3.cpp) +target_link_libraries(foo bar) +# The last element here needs to contain a space so that it is a single +# element which is not a valid target name. As bar is a STATIC library, +# this tests that the LINK_ONLY generator expression is not used for +# that element, creating an error. +target_link_libraries(bar bat "-lz -lm") diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-empty-old-result.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-empty-old-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-empty-old-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-empty-old-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-empty-old-stderr.txt new file mode 100644 index 000000000..6a6a0c782 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-empty-old-stderr.txt @@ -0,0 +1,19 @@ +CMake Warning \(dev\) in CMakeLists.txt: + Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link + interface. Run "cmake --help-policy CMP0022" for policy details. Use the + cmake_policy command to set the policy and suppress this warning. + + Target "bar" has an INTERFACE_LINK_LIBRARIES property. This should be + preferred as the source of the link interface for this library but because + CMP0022 is not set CMake is ignoring the property and using the link + implementation as the link interface instead. + + INTERFACE_LINK_LIBRARIES: + + foo + + Link implementation: + + \(empty\) + +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-empty-old.cmake b/Tests/RunCMake/CMP0022/CMP0022-WARN-empty-old.cmake new file mode 100644 index 000000000..c5d3c29d9 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-empty-old.cmake @@ -0,0 +1,10 @@ + +project(CMP0022-WARN-empty-old) + +add_library(foo SHARED empty_vs6_1.cpp) +add_library(bar SHARED empty_vs6_2.cpp) + +set_property(TARGET bar PROPERTY INTERFACE_LINK_LIBRARIES foo) + +add_library(user empty.cpp) +target_link_libraries(user bar) diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-static-result.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-static-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-static-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-static-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-static-stderr.txt new file mode 100644 index 000000000..1370c5ebe --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-static-stderr.txt @@ -0,0 +1,19 @@ +CMake Warning \(dev\) in CMakeLists.txt: + Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link + interface. Run "cmake --help-policy CMP0022" for policy details. Use the + cmake_policy command to set the policy and suppress this warning. + + Target "bar" has an INTERFACE_LINK_LIBRARIES property. This should be + preferred as the source of the link interface for this library but because + CMP0022 is not set CMake is ignoring the property and using the link + implementation as the link interface instead. + + INTERFACE_LINK_LIBRARIES: + + foo + + Link implementation: + + bat + +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-static.cmake b/Tests/RunCMake/CMP0022/CMP0022-WARN-static.cmake new file mode 100644 index 000000000..b3cb13160 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-static.cmake @@ -0,0 +1,11 @@ + +project(CMP0022-WARN) + +add_library(foo STATIC empty_vs6_1.cpp) +add_library(bar STATIC empty_vs6_2.cpp) +add_library(bat STATIC empty_vs6_3.cpp) +set_property(TARGET bar PROPERTY INTERFACE_LINK_LIBRARIES foo) +set_property(TARGET bar PROPERTY LINK_LIBRARIES bat) + +add_library(user empty.cpp) +target_link_libraries(user bar) diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-stderr.txt new file mode 100644 index 000000000..2f7dfbfb7 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-stderr.txt @@ -0,0 +1,17 @@ +^CMake Warning \(dev\) in CMakeLists.txt: + Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link + interface. Run "cmake --help-policy CMP0022" for policy details. Use the + cmake_policy command to set the policy and suppress this warning. + + Target "bar" has an INTERFACE_LINK_LIBRARIES property which differs from + its LINK_INTERFACE_LIBRARIES properties. + + INTERFACE_LINK_LIBRARIES: + + foo + + LINK_INTERFACE_LIBRARIES: + + bat + +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-result.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt new file mode 100644 index 000000000..f6722853a --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt @@ -0,0 +1,17 @@ +CMake Warning \(dev\) in CMakeLists.txt: + Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link + interface. Run "cmake --help-policy CMP0022" for policy details. Use the + cmake_policy command to set the policy and suppress this warning. + + Target "bar" has an INTERFACE_LINK_LIBRARIES property which differs from + its LINK_INTERFACE_LIBRARIES properties. + + INTERFACE_LINK_LIBRARIES: + + foo + + LINK_INTERFACE_LIBRARIES: + + bat + +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake new file mode 100644 index 000000000..11b4e22a9 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake @@ -0,0 +1,11 @@ + +project(CMP0022-WARN-tll) + +add_library(foo SHARED empty_vs6_1.cpp) +add_library(bar SHARED empty_vs6_2.cpp) +add_library(bat SHARED empty_vs6_3.cpp) +target_link_libraries(bar LINK_PUBLIC foo) +set_property(TARGET bar PROPERTY LINK_INTERFACE_LIBRARIES bat) + +add_library(user SHARED empty.cpp) +target_link_libraries(user bar) diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN.cmake b/Tests/RunCMake/CMP0022/CMP0022-WARN.cmake new file mode 100644 index 000000000..fe7e858b7 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN.cmake @@ -0,0 +1,16 @@ + +project(CMP0022-WARN) + +add_library(foo SHARED empty_vs6_1.cpp) +add_library(bar SHARED empty_vs6_2.cpp) +add_library(bat SHARED empty_vs6_3.cpp) +set_property(TARGET bar PROPERTY INTERFACE_LINK_LIBRARIES foo) +set_property(TARGET bar PROPERTY LINK_INTERFACE_LIBRARIES bat) + +add_library(user empty.cpp) +target_link_libraries(user bar) + +# Use "bar" again with a different "head" target to check +# that the warning does not appear again. +add_library(user2 empty_vs6_3.cpp) +target_link_libraries(user2 bar) diff --git a/Tests/RunCMake/CMP0022/CMP0022-export-exe-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-export-exe-stderr.txt new file mode 100644 index 000000000..10f32932e --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-export-exe-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/CMP0022/CMP0022-export-exe.cmake b/Tests/RunCMake/CMP0022/CMP0022-export-exe.cmake new file mode 100644 index 000000000..d832faceb --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-export-exe.cmake @@ -0,0 +1,9 @@ +enable_language(CXX) + +cmake_policy(SET CMP0022 NEW) + +add_library(testLib empty_vs6_1.cpp) +add_executable(testExe empty_vs6_2.cpp) +target_link_libraries(testExe testLib) + +export(TARGETS testExe FILE "${CMAKE_CURRENT_BINARY_DIR}/cmp0022NEW-exe.cmake") diff --git a/Tests/RunCMake/CMP0022/CMP0022-export-result.txt b/Tests/RunCMake/CMP0022/CMP0022-export-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-export-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt new file mode 100644 index 000000000..ae7627e1e --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at CMP0022-export.cmake:11 \(export\): + Target "cmp0022NEW" has policy CMP0022 enabled, but also has old-style + LINK_INTERFACE_LIBRARIES properties populated, but it was exported without + the EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties diff --git a/Tests/RunCMake/CMP0022/CMP0022-export.cmake b/Tests/RunCMake/CMP0022/CMP0022-export.cmake new file mode 100644 index 000000000..06147f39e --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-export.cmake @@ -0,0 +1,11 @@ + +project(cmp0022NEW) + +cmake_policy(SET CMP0022 NEW) + +add_library(cmp0022NEW SHARED empty_vs6_1.cpp) +add_library(testLib SHARED empty_vs6_2.cpp) + +set_property(TARGET cmp0022NEW APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLib) + +export(TARGETS cmp0022NEW testLib FILE "${CMAKE_CURRENT_BINARY_DIR}/cmp0022NEW.cmake") diff --git a/Tests/RunCMake/CMP0022/CMP0022-install-export-result.txt b/Tests/RunCMake/CMP0022/CMP0022-install-export-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-install-export-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0022/CMP0022-install-export-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-install-export-stderr.txt new file mode 100644 index 000000000..405dd8dc8 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-install-export-stderr.txt @@ -0,0 +1,4 @@ +CMake Error in CMakeLists.txt: + Target "cmp0022NEW" has policy CMP0022 enabled, but also has old-style + LINK_INTERFACE_LIBRARIES properties populated, but it was exported without + the EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties diff --git a/Tests/RunCMake/CMP0022/CMP0022-install-export.cmake b/Tests/RunCMake/CMP0022/CMP0022-install-export.cmake new file mode 100644 index 000000000..171febe3a --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMP0022-install-export.cmake @@ -0,0 +1,12 @@ + +project(cmp0022NEW) + +cmake_policy(SET CMP0022 NEW) + +add_library(cmp0022NEW SHARED empty_vs6_1.cpp) +add_library(testLib SHARED empty_vs6_2.cpp) + +set_property(TARGET cmp0022NEW APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLib) + +install(TARGETS cmp0022NEW testLib EXPORT exp DESTINATION lib) +install(EXPORT exp FILE expTargets.cmake DESTINATION lib/cmake/exp) diff --git a/Tests/RunCMake/CMP0022/CMakeLists.txt b/Tests/RunCMake/CMP0022/CMakeLists.txt new file mode 100644 index 000000000..72abfc809 --- /dev/null +++ b/Tests/RunCMake/CMP0022/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.11) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0022/RunCMakeTest.cmake b/Tests/RunCMake/CMP0022/RunCMakeTest.cmake new file mode 100644 index 000000000..2781d2094 --- /dev/null +++ b/Tests/RunCMake/CMP0022/RunCMakeTest.cmake @@ -0,0 +1,13 @@ +include(RunCMake) + +run_cmake(CMP0022-WARN) +run_cmake(CMP0022-WARN-tll) +run_cmake(CMP0022-WARN-static) +run_cmake(CMP0022-WARN-empty-old) +run_cmake(CMP0022-NOWARN-exe) +run_cmake(CMP0022-NOWARN-shared) +run_cmake(CMP0022-NOWARN-static) +run_cmake(CMP0022-NOWARN-static-link_libraries) +run_cmake(CMP0022-export) +run_cmake(CMP0022-export-exe) +run_cmake(CMP0022-install-export) diff --git a/Tests/RunCMake/CMP0022/dep1/CMakeLists.txt b/Tests/RunCMake/CMP0022/dep1/CMakeLists.txt new file mode 100644 index 000000000..f0a817923 --- /dev/null +++ b/Tests/RunCMake/CMP0022/dep1/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_library(dep1 ../empty_vs6_1.cpp) diff --git a/Tests/RunCMake/CMP0022/dep2/CMakeLists.txt b/Tests/RunCMake/CMP0022/dep2/CMakeLists.txt new file mode 100644 index 000000000..4f90162f8 --- /dev/null +++ b/Tests/RunCMake/CMP0022/dep2/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_library(dep2 ../empty_vs6_2.cpp) diff --git a/Tests/RunCMake/CMP0022/dep3/CMakeLists.txt b/Tests/RunCMake/CMP0022/dep3/CMakeLists.txt new file mode 100644 index 000000000..e85cb5431 --- /dev/null +++ b/Tests/RunCMake/CMP0022/dep3/CMakeLists.txt @@ -0,0 +1,5 @@ + +link_libraries(dep1) + +add_library(dep3 ../empty_vs6_3.cpp) +target_link_libraries(dep3 dep2) diff --git a/Tests/RunCMake/CMP0022/empty.cpp b/Tests/RunCMake/CMP0022/empty.cpp new file mode 100644 index 000000000..bfbbddeb9 --- /dev/null +++ b/Tests/RunCMake/CMP0022/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/CMP0022/empty_vs6_1.cpp b/Tests/RunCMake/CMP0022/empty_vs6_1.cpp new file mode 100644 index 000000000..7efedabfa --- /dev/null +++ b/Tests/RunCMake/CMP0022/empty_vs6_1.cpp @@ -0,0 +1 @@ +#include "empty.cpp" diff --git a/Tests/RunCMake/CMP0022/empty_vs6_2.cpp b/Tests/RunCMake/CMP0022/empty_vs6_2.cpp new file mode 100644 index 000000000..7efedabfa --- /dev/null +++ b/Tests/RunCMake/CMP0022/empty_vs6_2.cpp @@ -0,0 +1 @@ +#include "empty.cpp" diff --git a/Tests/RunCMake/CMP0022/empty_vs6_3.cpp b/Tests/RunCMake/CMP0022/empty_vs6_3.cpp new file mode 100644 index 000000000..7efedabfa --- /dev/null +++ b/Tests/RunCMake/CMP0022/empty_vs6_3.cpp @@ -0,0 +1 @@ +#include "empty.cpp" diff --git a/Tests/RunCMake/CMP0022/empty_vs6_4.cpp b/Tests/RunCMake/CMP0022/empty_vs6_4.cpp new file mode 100644 index 000000000..7efedabfa --- /dev/null +++ b/Tests/RunCMake/CMP0022/empty_vs6_4.cpp @@ -0,0 +1 @@ +#include "empty.cpp" diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 402c8a980..e45aba378 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -28,7 +28,7 @@ # <SubTest>-stdout.txt = Regex matching expected stdout content # <SubTest>-stderr.txt = Regex matching expected stderr content # <SubTest>-check.cmake = Custom result check -# Note that trailing newlines will be stripped from actual test +# Note that trailing newlines will be stripped from actual and expected test # output before matching against the stdout and stderr expressions. # The code in <SubTest>-check.cmake may use variables # RunCMake_TEST_SOURCE_DIR = Top of test source tree @@ -52,10 +52,12 @@ if(XCODE_VERSION AND "${XCODE_VERSION}" VERSION_LESS 3) endif() add_RunCMake_test(CMP0019) +add_RunCMake_test(CMP0022) add_RunCMake_test(CTest) if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles") add_RunCMake_test(CompilerChange) endif() +add_RunCMake_test(Configure) add_RunCMake_test(ExternalData) add_RunCMake_test(FPHSA) add_RunCMake_test(GeneratorExpression) @@ -65,24 +67,55 @@ add_RunCMake_test(Languages) add_RunCMake_test(ObjectLibrary) if(NOT WIN32) add_RunCMake_test(PositionIndependentCode) + set(SKIP_VISIBILITY 0) + if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 4.2) + set(SKIP_VISIBILITY 1) + endif() + + if (CMAKE_CXX_COMPILER_ID MATCHES Watcom + OR CMAKE_SYSTEM_NAME MATCHES IRIX64 + OR CMAKE_CXX_COMPILER_ID MATCHES HP + OR CMAKE_CXX_COMPILER_ID MATCHES XL + OR CMAKE_CXX_COMPILER_ID MATCHES SunPro) + set(SKIP_VISIBILITY 1) + endif() + + if (NOT SKIP_VISIBILITY) + add_RunCMake_test(VisibilityPreset) + endif() endif() add_RunCMake_test(CompatibleInterface) +add_RunCMake_test(Syntax) add_RunCMake_test(add_dependencies) add_RunCMake_test(build_command) add_RunCMake_test(find_package) +add_RunCMake_test(get_filename_component) +add_RunCMake_test(if) add_RunCMake_test(include) add_RunCMake_test(include_directories) add_RunCMake_test(list) +add_RunCMake_test(try_compile) +add_RunCMake_test(variable_watch) add_RunCMake_test(CMP0004) +add_RunCMake_test(TargetPolicies) +add_RunCMake_test(alias_targets) find_package(Qt4 QUIET) find_package(Qt5Core QUIET) if (QT4_FOUND AND Qt5Core_FOUND AND NOT Qt5Core_VERSION VERSION_LESS 5.1.0) add_RunCMake_test(IncompatibleQt) endif() +if (QT4_FOUND) + set(ObsoleteQtMacros_ARGS -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}) + add_RunCMake_test(ObsoleteQtMacros) +endif() if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]") add_RunCMake_test(include_external_msproject) add_RunCMake_test(SolutionGlobalSections) endif() + +add_RunCMake_test(File_Generate) +add_RunCMake_test(ExportWithoutLanguage) +add_RunCMake_test(target_link_libraries) diff --git a/Tests/RunCMake/CTest/CMakeLists.txt b/Tests/RunCMake/CTest/CMakeLists.txt index f6e84c04d..73e6a785a 100644 --- a/Tests/RunCMake/CTest/CMakeLists.txt +++ b/Tests/RunCMake/CTest/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) if(NOT NoProject) project(${RunCMake_TEST} NONE) endif() diff --git a/Tests/RunCMake/CompatibleInterface/CMakeLists.txt b/Tests/RunCMake/CompatibleInterface/CMakeLists.txt index 68dd8d6a1..f452db177 100644 --- a/Tests/RunCMake/CompatibleInterface/CMakeLists.txt +++ b/Tests/RunCMake/CompatibleInterface/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} CXX) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CompilerChange/CMakeLists.txt b/Tests/RunCMake/CompilerChange/CMakeLists.txt index 3b925188d..b4b30165f 100644 --- a/Tests/RunCMake/CompilerChange/CMakeLists.txt +++ b/Tests/RunCMake/CompilerChange/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) if(NOT RunCMake_TEST) set(RunCMake_TEST "$ENV{RunCMake_TEST}") # needed when cache is deleted endif() diff --git a/Tests/RunCMake/Configure/CMakeLists.txt b/Tests/RunCMake/Configure/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/Configure/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Configure/ErrorLogs-result.txt b/Tests/RunCMake/Configure/ErrorLogs-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/Configure/ErrorLogs-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Configure/ErrorLogs-stderr.txt b/Tests/RunCMake/Configure/ErrorLogs-stderr.txt new file mode 100644 index 000000000..4eee45dbc --- /dev/null +++ b/Tests/RunCMake/Configure/ErrorLogs-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at ErrorLogs.cmake:3 \(message\): + Some error! +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/Configure/ErrorLogs-stdout.txt b/Tests/RunCMake/Configure/ErrorLogs-stdout.txt new file mode 100644 index 000000000..c467b6204 --- /dev/null +++ b/Tests/RunCMake/Configure/ErrorLogs-stdout.txt @@ -0,0 +1,3 @@ +-- Configuring incomplete, errors occurred! +See also ".*/Tests/RunCMake/Configure/ErrorLogs-build/CMakeFiles/CMakeOutput\.log"\. +See also ".*/Tests/RunCMake/Configure/ErrorLogs-build/CMakeFiles/CMakeError\.log"\. diff --git a/Tests/RunCMake/Configure/ErrorLogs.cmake b/Tests/RunCMake/Configure/ErrorLogs.cmake new file mode 100644 index 000000000..e8cf06266 --- /dev/null +++ b/Tests/RunCMake/Configure/ErrorLogs.cmake @@ -0,0 +1,3 @@ +file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Some detailed error information!\n") +message(SEND_ERROR "Some error!") diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake b/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake new file mode 100644 index 000000000..db0cb0a34 --- /dev/null +++ b/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake @@ -0,0 +1,14 @@ +set(log "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/CMakeError.log") +if(EXISTS "${log}") + file(READ "${log}" error_log) +else() + set(error_log "") +endif() +string(REPLACE "\r\n" "\n" regex "Cannot copy output executable.* +to destination specified by COPY_FILE:.* +Unable to find the executable at any of: + .*\\.missing") +if(NOT error_log MATCHES "${regex}") + string(REGEX REPLACE "\n" "\n " error_log " ${error_log}") + set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected COPY_FILE failure message:\n${error_log}") +endif() diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake b/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake new file mode 100644 index 000000000..c633555b6 --- /dev/null +++ b/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake @@ -0,0 +1,6 @@ +# Change the executable suffix that try_compile will use for +# COPY_FILE but not inside the test project. This forces failure. +get_property(in_try_compile GLOBAL PROPERTY IN_TRY_COMPILE) +if(NOT in_try_compile) + set(CMAKE_EXECUTABLE_SUFFIX .missing) +endif() diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt b/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt new file mode 100644 index 000000000..bb87f4c31 --- /dev/null +++ b/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt @@ -0,0 +1,4 @@ +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - failed +-- Configuring done +-- Generating done diff --git a/Tests/RunCMake/Configure/FailCopyFileABI.cmake b/Tests/RunCMake/Configure/FailCopyFileABI.cmake new file mode 100644 index 000000000..74efd9720 --- /dev/null +++ b/Tests/RunCMake/Configure/FailCopyFileABI.cmake @@ -0,0 +1,2 @@ +set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/FailCopyFileABI-override.cmake) +enable_language(C) diff --git a/Tests/RunCMake/Configure/RunCMakeTest.cmake b/Tests/RunCMake/Configure/RunCMakeTest.cmake new file mode 100644 index 000000000..79e4060cc --- /dev/null +++ b/Tests/RunCMake/Configure/RunCMakeTest.cmake @@ -0,0 +1,4 @@ +include(RunCMake) + +run_cmake(ErrorLogs) +run_cmake(FailCopyFileABI) diff --git a/Tests/RunCMake/ExportWithoutLanguage/CMakeLists.txt b/Tests/RunCMake/ExportWithoutLanguage/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/ExportWithoutLanguage/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/ExportWithoutLanguage/NoLanguage-result.txt b/Tests/RunCMake/ExportWithoutLanguage/NoLanguage-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/ExportWithoutLanguage/NoLanguage-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ExportWithoutLanguage/NoLanguage-stderr.txt b/Tests/RunCMake/ExportWithoutLanguage/NoLanguage-stderr.txt new file mode 100644 index 000000000..67a0ae37c --- /dev/null +++ b/Tests/RunCMake/ExportWithoutLanguage/NoLanguage-stderr.txt @@ -0,0 +1,6 @@ +CMake Error: CMake can not determine linker language for target: NoLanguage +CMake Error at NoLanguage.cmake:2 \(export\): + Exporting the target "NoLanguage" is not allowed since its linker language + cannot be determined +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ExportWithoutLanguage/NoLanguage.cmake b/Tests/RunCMake/ExportWithoutLanguage/NoLanguage.cmake new file mode 100644 index 000000000..2ede85431 --- /dev/null +++ b/Tests/RunCMake/ExportWithoutLanguage/NoLanguage.cmake @@ -0,0 +1,2 @@ +add_library(NoLanguage header.h) +export(TARGETS NoLanguage FILE "${CMAKE_CURRENT_BINARY_DIR}/export.cmake") diff --git a/Tests/RunCMake/ExportWithoutLanguage/RunCMakeTest.cmake b/Tests/RunCMake/ExportWithoutLanguage/RunCMakeTest.cmake new file mode 100644 index 000000000..f77f4eba0 --- /dev/null +++ b/Tests/RunCMake/ExportWithoutLanguage/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(NoLanguage) diff --git a/Tests/RunCMake/ExternalData/CMakeLists.txt b/Tests/RunCMake/ExternalData/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/ExternalData/CMakeLists.txt +++ b/Tests/RunCMake/ExternalData/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/FPHSA/CMakeLists.txt b/Tests/RunCMake/FPHSA/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/FPHSA/CMakeLists.txt +++ b/Tests/RunCMake/FPHSA/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/File_Generate/BadCondition-result.txt b/Tests/RunCMake/File_Generate/BadCondition-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/File_Generate/BadCondition-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Generate/BadCondition-stderr.txt b/Tests/RunCMake/File_Generate/BadCondition-stderr.txt new file mode 100644 index 000000000..bab836843 --- /dev/null +++ b/Tests/RunCMake/File_Generate/BadCondition-stderr.txt @@ -0,0 +1,3 @@ +CMake Error in CMakeLists.txt: + Evaluation file condition \"\$<1:Bad>\" did not evaluate to valid content. + Got \"Bad\". diff --git a/Tests/RunCMake/File_Generate/BadCondition.cmake b/Tests/RunCMake/File_Generate/BadCondition.cmake new file mode 100644 index 000000000..82ad672ad --- /dev/null +++ b/Tests/RunCMake/File_Generate/BadCondition.cmake @@ -0,0 +1,5 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION $<1:Bad> +) diff --git a/Tests/RunCMake/File_Generate/CMakeLists.txt b/Tests/RunCMake/File_Generate/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/File_Generate/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/File_Generate/CommandConflict-result.txt b/Tests/RunCMake/File_Generate/CommandConflict-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/File_Generate/CommandConflict-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Generate/CommandConflict-stderr.txt b/Tests/RunCMake/File_Generate/CommandConflict-stderr.txt new file mode 100644 index 000000000..da97ba476 --- /dev/null +++ b/Tests/RunCMake/File_Generate/CommandConflict-stderr.txt @@ -0,0 +1 @@ +CMake Error: File to be generated by multiple different commands: .*CommandConflict-build/output_.*.txt diff --git a/Tests/RunCMake/File_Generate/CommandConflict.cmake b/Tests/RunCMake/File_Generate/CommandConflict.cmake new file mode 100644 index 000000000..d57bc1284 --- /dev/null +++ b/Tests/RunCMake/File_Generate/CommandConflict.cmake @@ -0,0 +1,9 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output_$<CONFIGURATION>.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION $<CONFIG:$<CONFIGURATION>> +) +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output_$<CONFIGURATION>.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION $<CONFIG:$<CONFIGURATION>> +) diff --git a/Tests/RunCMake/File_Generate/DebugEvaluate.cmake b/Tests/RunCMake/File_Generate/DebugEvaluate.cmake new file mode 100644 index 000000000..1fa9b62bb --- /dev/null +++ b/Tests/RunCMake/File_Generate/DebugEvaluate.cmake @@ -0,0 +1,5 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION $<CONFIG:Debug> +) diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1-result.txt b/Tests/RunCMake/File_Generate/EmptyCondition1-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt new file mode 100644 index 000000000..9fe39cca6 --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at EmptyCondition1.cmake:2 \(file\): + file Incorrect arguments to GENERATE subcommand. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1.cmake b/Tests/RunCMake/File_Generate/EmptyCondition1.cmake new file mode 100644 index 000000000..8574a5f7d --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition1.cmake @@ -0,0 +1,5 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION +) diff --git a/Tests/RunCMake/File_Generate/EmptyCondition2-result.txt b/Tests/RunCMake/File_Generate/EmptyCondition2-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Generate/EmptyCondition2-stderr.txt b/Tests/RunCMake/File_Generate/EmptyCondition2-stderr.txt new file mode 100644 index 000000000..73d5f2504 --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition2-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at EmptyCondition2.cmake:2 \(file\): + file CONDITION of sub-command GENERATE must not be empty if specified. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/File_Generate/EmptyCondition2.cmake b/Tests/RunCMake/File_Generate/EmptyCondition2.cmake new file mode 100644 index 000000000..626bfb4c4 --- /dev/null +++ b/Tests/RunCMake/File_Generate/EmptyCondition2.cmake @@ -0,0 +1,5 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" + CONDITION "" +) diff --git a/Tests/RunCMake/File_Generate/OutputConflict-result.txt b/Tests/RunCMake/File_Generate/OutputConflict-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/File_Generate/OutputConflict-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt new file mode 100644 index 000000000..dbd39de50 --- /dev/null +++ b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt @@ -0,0 +1,5 @@ +CMake Error in CMakeLists.txt: + Evaluation file to be written multiple times for different configurations + with different content: + + .*output.txt diff --git a/Tests/RunCMake/File_Generate/OutputConflict.cmake b/Tests/RunCMake/File_Generate/OutputConflict.cmake new file mode 100644 index 000000000..7f3e8c7c7 --- /dev/null +++ b/Tests/RunCMake/File_Generate/OutputConflict.cmake @@ -0,0 +1,4 @@ + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" +) diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake new file mode 100644 index 000000000..f07431c0e --- /dev/null +++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake @@ -0,0 +1,10 @@ +include(RunCMake) + +run_cmake(CommandConflict) +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio" OR "${RunCMake_GENERATOR}" MATCHES "XCode" ) + run_cmake(OutputConflict) +endif() +run_cmake(EmptyCondition1) +run_cmake(EmptyCondition2) +run_cmake(BadCondition) +run_cmake(DebugEvaluate) diff --git a/Tests/RunCMake/File_Generate/input.txt b/Tests/RunCMake/File_Generate/input.txt new file mode 100644 index 000000000..3db429d21 --- /dev/null +++ b/Tests/RunCMake/File_Generate/input.txt @@ -0,0 +1 @@ +Some $<$<CONFIG:Debug>:conflicting> $<$<NOT:$<CONFIG:Debug>>:content> diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject-result.txt b/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject-stderr.txt new file mode 100644 index 000000000..533d38cef --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject-stderr.txt @@ -0,0 +1,26 @@ +CMake Error at BadTargetTypeObject.cmake:3 \(add_custom_target\): + Error evaluating generator expression: + + \$<TARGET_FILE:objlib> + + Target "objlib" is not an executable or library. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Error at BadTargetTypeObject.cmake:3 \(add_custom_target\): + Error evaluating generator expression: + + \$<TARGET_SONAME_FILE:objlib> + + Target "objlib" is not an executable or library. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Error at BadTargetTypeObject.cmake:3 \(add_custom_target\): + Error evaluating generator expression: + + \$<TARGET_LINKER_FILE:objlib> + + Target "objlib" is not an executable or library. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject.cmake b/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject.cmake new file mode 100644 index 000000000..c47ee2bec --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject.cmake @@ -0,0 +1,7 @@ +enable_language(C) +add_library(objlib OBJECT empty.c) +add_custom_target(check ALL COMMAND echo + $<TARGET_FILE:objlib> + $<TARGET_SONAME_FILE:objlib> + $<TARGET_LINKER_FILE:objlib> + ) diff --git a/Tests/RunCMake/GeneratorExpression/CMakeLists.txt b/Tests/RunCMake/GeneratorExpression/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/GeneratorExpression/CMakeLists.txt +++ b/Tests/RunCMake/GeneratorExpression/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake index 62bf29bc9..54d5064ce 100644 --- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake @@ -7,4 +7,5 @@ run_cmake(BadNOT) run_cmake(BadStrEqual) run_cmake(BadZero) run_cmake(BadTargetName) +run_cmake(BadTargetTypeObject) run_cmake(BadInstallPrefix) diff --git a/Tests/RunCMake/GeneratorExpression/empty.c b/Tests/RunCMake/GeneratorExpression/empty.c new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/empty.c diff --git a/Tests/RunCMake/GeneratorToolset/CMakeLists.txt b/Tests/RunCMake/GeneratorToolset/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/GeneratorToolset/CMakeLists.txt +++ b/Tests/RunCMake/GeneratorToolset/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/IncompatibleQt/CMakeLists.txt b/Tests/RunCMake/IncompatibleQt/CMakeLists.txt index 68dd8d6a1..f452db177 100644 --- a/Tests/RunCMake/IncompatibleQt/CMakeLists.txt +++ b/Tests/RunCMake/IncompatibleQt/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} CXX) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Languages/CMakeLists.txt b/Tests/RunCMake/Languages/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/Languages/CMakeLists.txt +++ b/Tests/RunCMake/Languages/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Languages/LINK_LANGUAGE-genex-result.txt b/Tests/RunCMake/Languages/LINK_LANGUAGE-genex-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/Languages/LINK_LANGUAGE-genex-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Languages/LINK_LANGUAGE-genex-stderr.txt b/Tests/RunCMake/Languages/LINK_LANGUAGE-genex-stderr.txt new file mode 100644 index 000000000..a5d5d5088 --- /dev/null +++ b/Tests/RunCMake/Languages/LINK_LANGUAGE-genex-stderr.txt @@ -0,0 +1,7 @@ +CMake Error: + Error evaluating generator expression: + + \$<TARGET_PROPERTY:LINKER_LANGUAGE> + + LINKER_LANGUAGE target property can not be used while evaluating link + libraries diff --git a/Tests/RunCMake/Languages/LINK_LANGUAGE-genex.cmake b/Tests/RunCMake/Languages/LINK_LANGUAGE-genex.cmake new file mode 100644 index 000000000..64f394c11 --- /dev/null +++ b/Tests/RunCMake/Languages/LINK_LANGUAGE-genex.cmake @@ -0,0 +1,4 @@ + +add_library(foo STATIC empty.cpp) +add_library(bar STATIC empty.cpp) +target_link_libraries(foo $<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,anything>:bar>) diff --git a/Tests/RunCMake/Languages/NoLangSHARED-stderr.txt b/Tests/RunCMake/Languages/NoLangSHARED-stderr.txt index 3f93cf86c..983129a21 100644 --- a/Tests/RunCMake/Languages/NoLangSHARED-stderr.txt +++ b/Tests/RunCMake/Languages/NoLangSHARED-stderr.txt @@ -1 +1 @@ -CMake Error: CMake can not determine linker language for target:NoLang +CMake Error: CMake can not determine linker language for target: NoLang diff --git a/Tests/RunCMake/Languages/RunCMakeTest.cmake b/Tests/RunCMake/Languages/RunCMakeTest.cmake index a99548f05..6517a8105 100644 --- a/Tests/RunCMake/Languages/RunCMakeTest.cmake +++ b/Tests/RunCMake/Languages/RunCMakeTest.cmake @@ -1,3 +1,6 @@ include(RunCMake) run_cmake(NoLangSHARED) +run_cmake(LINK_LANGUAGE-genex) +run_cmake(link-libraries-TARGET_FILE-genex) +run_cmake(link-libraries-TARGET_FILE-genex-ok) diff --git a/Tests/RunCMake/Languages/empty.cpp b/Tests/RunCMake/Languages/empty.cpp new file mode 100644 index 000000000..7279c5e0b --- /dev/null +++ b/Tests/RunCMake/Languages/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty(void) +{ + return 0; +} diff --git a/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-ok-result.txt b/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-ok-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-ok-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-ok.cmake b/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-ok.cmake new file mode 100644 index 000000000..f0fd6e5aa --- /dev/null +++ b/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-ok.cmake @@ -0,0 +1,6 @@ + +enable_language(CXX) + +add_library(foo SHARED empty.cpp) +add_library(bar SHARED empty.cpp) +target_link_libraries(foo $<$<STREQUAL:$<TARGET_FILE:bar>,anything>:bar>) diff --git a/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-result.txt b/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-stderr.txt b/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-stderr.txt new file mode 100644 index 000000000..2d7a3c9d6 --- /dev/null +++ b/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex-stderr.txt @@ -0,0 +1,7 @@ +CMake Error: + Error evaluating generator expression: + + \$<TARGET_FILE:foo> + + Expressions which require the linker language may not be used while + evaluating link libraries diff --git a/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex.cmake b/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex.cmake new file mode 100644 index 000000000..eca73e977 --- /dev/null +++ b/Tests/RunCMake/Languages/link-libraries-TARGET_FILE-genex.cmake @@ -0,0 +1,4 @@ + +add_library(foo SHARED empty.cpp) +add_library(bar SHARED empty.cpp) +target_link_libraries(foo $<$<STREQUAL:$<TARGET_FILE:foo>,anything>:bar>) diff --git a/Tests/RunCMake/ObjectLibrary/CMakeLists.txt b/Tests/RunCMake/ObjectLibrary/CMakeLists.txt index a7f077912..a17c8cd13 100644 --- a/Tests/RunCMake/ObjectLibrary/CMakeLists.txt +++ b/Tests/RunCMake/ObjectLibrary/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} C) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/ObjectLibrary/MissingSource-result.txt b/Tests/RunCMake/ObjectLibrary/MissingSource-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/MissingSource-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/MissingSource-stderr.txt b/Tests/RunCMake/ObjectLibrary/MissingSource-stderr.txt new file mode 100644 index 000000000..411cd7cb7 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/MissingSource-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at MissingSource.cmake:1 \(add_library\): + Cannot find source file: + + missing.c + + Tried extensions( \.[A-Za-z+]+| + )* +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/MissingSource.cmake b/Tests/RunCMake/ObjectLibrary/MissingSource.cmake new file mode 100644 index 000000000..258eaedb2 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/MissingSource.cmake @@ -0,0 +1 @@ +add_library(A OBJECT missing.c) diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake index 55db14dfd..2dd8d3859 100644 --- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake @@ -12,6 +12,7 @@ run_cmake(Install) run_cmake(LinkObjLHS) run_cmake(LinkObjRHS1) run_cmake(LinkObjRHS2) +run_cmake(MissingSource) run_cmake(ObjWithObj) run_cmake(PostBuild) run_cmake(PreBuild) diff --git a/Tests/RunCMake/ObsoleteQtMacros/AutomocMacro-WARN-result.txt b/Tests/RunCMake/ObsoleteQtMacros/AutomocMacro-WARN-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/ObsoleteQtMacros/AutomocMacro-WARN-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/ObsoleteQtMacros/AutomocMacro-WARN-stderr.txt b/Tests/RunCMake/ObsoleteQtMacros/AutomocMacro-WARN-stderr.txt new file mode 100644 index 000000000..6f7e8ee61 --- /dev/null +++ b/Tests/RunCMake/ObsoleteQtMacros/AutomocMacro-WARN-stderr.txt @@ -0,0 +1,5 @@ +CMake Warning at .*/Modules/Qt4Macros.cmake:[^ ]+ \(message\): + The qt4_automoc macro is obsolete. Use the CMAKE_AUTOMOC feature instead. +Call Stack \(most recent call first\): + AutomocMacro-WARN.cmake:7 \(qt4_automoc\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObsoleteQtMacros/AutomocMacro-WARN.cmake b/Tests/RunCMake/ObsoleteQtMacros/AutomocMacro-WARN.cmake new file mode 100644 index 000000000..c0c64a5b7 --- /dev/null +++ b/Tests/RunCMake/ObsoleteQtMacros/AutomocMacro-WARN.cmake @@ -0,0 +1,7 @@ + +find_package(Qt4 REQUIRED) + +set(CMAKE_WARN_DEPRECATED 1) + +add_library(foo SHARED empty.cpp) +qt4_automoc(foo_moc_srcs empty.cpp) diff --git a/Tests/RunCMake/ObsoleteQtMacros/CMakeLists.txt b/Tests/RunCMake/ObsoleteQtMacros/CMakeLists.txt new file mode 100644 index 000000000..65ac8e8db --- /dev/null +++ b/Tests/RunCMake/ObsoleteQtMacros/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.11) +project(${RunCMake_TEST}) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/ObsoleteQtMacros/RunCMakeTest.cmake b/Tests/RunCMake/ObsoleteQtMacros/RunCMakeTest.cmake new file mode 100644 index 000000000..eee2cc399 --- /dev/null +++ b/Tests/RunCMake/ObsoleteQtMacros/RunCMakeTest.cmake @@ -0,0 +1,6 @@ +include(RunCMake) + +set(RunCMake_TEST_OPTIONS -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}) + +run_cmake(UseModulesMacro-WARN) +run_cmake(AutomocMacro-WARN) diff --git a/Tests/RunCMake/ObsoleteQtMacros/UseModulesMacro-WARN-result.txt b/Tests/RunCMake/ObsoleteQtMacros/UseModulesMacro-WARN-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/ObsoleteQtMacros/UseModulesMacro-WARN-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/ObsoleteQtMacros/UseModulesMacro-WARN-stderr.txt b/Tests/RunCMake/ObsoleteQtMacros/UseModulesMacro-WARN-stderr.txt new file mode 100644 index 000000000..b90c6651a --- /dev/null +++ b/Tests/RunCMake/ObsoleteQtMacros/UseModulesMacro-WARN-stderr.txt @@ -0,0 +1,6 @@ +CMake Warning at .*/Modules/Qt4Macros.cmake:[^ ]+ \(message\): + The qt4_use_modules function is obsolete. Use target_link_libraries with + IMPORTED targets instead. +Call Stack \(most recent call first\): + UseModulesMacro-WARN.cmake:[^ ]+ \(qt4_use_modules\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObsoleteQtMacros/UseModulesMacro-WARN.cmake b/Tests/RunCMake/ObsoleteQtMacros/UseModulesMacro-WARN.cmake new file mode 100644 index 000000000..e86a3723b --- /dev/null +++ b/Tests/RunCMake/ObsoleteQtMacros/UseModulesMacro-WARN.cmake @@ -0,0 +1,7 @@ + +find_package(Qt4 REQUIRED) + +set(CMAKE_WARN_DEPRECATED 1) + +add_library(foo SHARED empty.cpp) +qt4_use_modules(foo LINK_PRIVATE Core) diff --git a/Tests/RunCMake/ObsoleteQtMacros/empty.cpp b/Tests/RunCMake/ObsoleteQtMacros/empty.cpp new file mode 100644 index 000000000..7279c5e0b --- /dev/null +++ b/Tests/RunCMake/ObsoleteQtMacros/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty(void) +{ + return 0; +} diff --git a/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt b/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt index 22577da4a..90afc127e 100644 --- a/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt +++ b/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} CXX) # MSVC creates extra targets which pollute the stderr unless we set this. diff --git a/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt b/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt +++ b/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Syntax/.gitattributes b/Tests/RunCMake/Syntax/.gitattributes new file mode 100644 index 000000000..fc9ebff69 --- /dev/null +++ b/Tests/RunCMake/Syntax/.gitattributes @@ -0,0 +1 @@ +CommandTabs.cmake whitespace=-tab-in-indent diff --git a/Tests/RunCMake/Syntax/BracketWarn-stderr.txt b/Tests/RunCMake/Syntax/BracketWarn-stderr.txt new file mode 100644 index 000000000..4a9cca641 --- /dev/null +++ b/Tests/RunCMake/Syntax/BracketWarn-stderr.txt @@ -0,0 +1,35 @@ +CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): + Syntax Warning in cmake code at + + .*/Tests/RunCMake/Syntax/BracketWarn.cmake:1:16 + + A future version of CMake may treat unquoted argument: + + \[\[ + + as an opening long bracket. Double-quote the argument. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): + Syntax Warning in cmake code at + + .*/Tests/RunCMake/Syntax/BracketWarn.cmake:1:19 + + A future version of CMake may treat unquoted argument: + + \[=\[ + + as an opening long bracket. Double-quote the argument. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): + Syntax Warning in cmake code at + + .*/Tests/RunCMake/Syntax/BracketWarn.cmake:1:27 + + A future version of CMake may treat unquoted argument: + + \[==\[x + + as an opening long bracket. Double-quote the argument. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/Syntax/BracketWarn-stdout.txt b/Tests/RunCMake/Syntax/BracketWarn-stdout.txt new file mode 100644 index 000000000..01b2caaa4 --- /dev/null +++ b/Tests/RunCMake/Syntax/BracketWarn-stdout.txt @@ -0,0 +1 @@ +-- \[\[\[=\[\[=x\[==\[x diff --git a/Tests/RunCMake/Syntax/BracketWarn.cmake b/Tests/RunCMake/Syntax/BracketWarn.cmake new file mode 100644 index 000000000..8f33946f0 --- /dev/null +++ b/Tests/RunCMake/Syntax/BracketWarn.cmake @@ -0,0 +1 @@ +message(STATUS [[ [=[ [=x [==[x) diff --git a/Tests/RunCMake/Syntax/CMakeLists.txt b/Tests/RunCMake/Syntax/CMakeLists.txt new file mode 100644 index 000000000..618473aaa --- /dev/null +++ b/Tests/RunCMake/Syntax/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.9) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Syntax/CommandComments-stderr.txt b/Tests/RunCMake/Syntax/CommandComments-stderr.txt new file mode 100644 index 000000000..df72cc5b9 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandComments-stderr.txt @@ -0,0 +1,4 @@ +Example Message +Example Message +Example Message +Second Line of Example diff --git a/Tests/RunCMake/Syntax/CommandComments.cmake b/Tests/RunCMake/Syntax/CommandComments.cmake new file mode 100644 index 000000000..0fd748452 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandComments.cmake @@ -0,0 +1,6 @@ +message("Example Message"#) + ) +message ("Example Message" # ) + ) +message( "Example Message\n" # "Commented" ) + "Second Line of Example") diff --git a/Tests/RunCMake/Syntax/CommandError0-result.txt b/Tests/RunCMake/Syntax/CommandError0-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandError0-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/CommandError0-stderr.txt b/Tests/RunCMake/Syntax/CommandError0-stderr.txt new file mode 100644 index 000000000..24d7997ad --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandError0-stderr.txt @@ -0,0 +1,8 @@ +CMake Error: Error in cmake code at +.*/Tests/RunCMake/Syntax/CommandError0.cmake:2: +Parse error. Expected "\(", got newline with text " +". +CMake Error at CMakeLists.txt:3 \(include\): + include could not find load file: + + CommandError0.cmake diff --git a/Tests/RunCMake/Syntax/CommandError0.cmake b/Tests/RunCMake/Syntax/CommandError0.cmake new file mode 100644 index 000000000..3222a9765 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandError0.cmake @@ -0,0 +1,2 @@ +message + ("Example Message") diff --git a/Tests/RunCMake/Syntax/CommandError1-result.txt b/Tests/RunCMake/Syntax/CommandError1-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandError1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/CommandError1-stderr.txt b/Tests/RunCMake/Syntax/CommandError1-stderr.txt new file mode 100644 index 000000000..599f60021 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandError1-stderr.txt @@ -0,0 +1,7 @@ +CMake Error: Error in cmake code at +.*/Tests/RunCMake/Syntax/CommandError1.cmake:1: +Parse error. Expected a newline, got identifier with text "message". +CMake Error at CMakeLists.txt:3 \(include\): + include could not find load file: + + CommandError1.cmake diff --git a/Tests/RunCMake/Syntax/CommandError1.cmake b/Tests/RunCMake/Syntax/CommandError1.cmake new file mode 100644 index 000000000..f8661a198 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandError1.cmake @@ -0,0 +1 @@ +message("Example Message") message("Second Message") diff --git a/Tests/RunCMake/Syntax/CommandNewlines-stderr.txt b/Tests/RunCMake/Syntax/CommandNewlines-stderr.txt new file mode 100644 index 000000000..571b15227 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandNewlines-stderr.txt @@ -0,0 +1,3 @@ +Example Message +Example Message +Example Message diff --git a/Tests/RunCMake/Syntax/CommandNewlines.cmake b/Tests/RunCMake/Syntax/CommandNewlines.cmake new file mode 100644 index 000000000..0587afb31 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandNewlines.cmake @@ -0,0 +1,10 @@ +message( + "Example Message") +message ( + "Example Message" + ) +message( + + "Example Message" + + ) diff --git a/Tests/RunCMake/Syntax/CommandSpaces-stderr.txt b/Tests/RunCMake/Syntax/CommandSpaces-stderr.txt new file mode 100644 index 000000000..54a8b3864 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandSpaces-stderr.txt @@ -0,0 +1,6 @@ +Example Message +Example Message +Example Message +Example Message +Example Message +Example Message diff --git a/Tests/RunCMake/Syntax/CommandSpaces.cmake b/Tests/RunCMake/Syntax/CommandSpaces.cmake new file mode 100644 index 000000000..5bd42945f --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandSpaces.cmake @@ -0,0 +1,6 @@ +message("Example Message") +message ("Example Message") +message( "Example Message" ) +message( "Example Message") + message ( "Example Message") +message ( Example " " Message ) diff --git a/Tests/RunCMake/Syntax/CommandTabs-stderr.txt b/Tests/RunCMake/Syntax/CommandTabs-stderr.txt new file mode 100644 index 000000000..54a8b3864 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandTabs-stderr.txt @@ -0,0 +1,6 @@ +Example Message +Example Message +Example Message +Example Message +Example Message +Example Message diff --git a/Tests/RunCMake/Syntax/CommandTabs.cmake b/Tests/RunCMake/Syntax/CommandTabs.cmake new file mode 100644 index 000000000..93876f862 --- /dev/null +++ b/Tests/RunCMake/Syntax/CommandTabs.cmake @@ -0,0 +1,6 @@ +message("Example Message") +message ("Example Message") +message( "Example Message" ) +message( "Example Message") + message ( "Example Message") +message ( Example " " Message ) diff --git a/Tests/RunCMake/Syntax/ParenNoSpace-stderr.txt b/Tests/RunCMake/Syntax/ParenNoSpace-stderr.txt new file mode 100644 index 000000000..10f32932e --- /dev/null +++ b/Tests/RunCMake/Syntax/ParenNoSpace-stderr.txt @@ -0,0 +1 @@ +^$ diff --git a/Tests/RunCMake/Syntax/ParenNoSpace-stdout.txt b/Tests/RunCMake/Syntax/ParenNoSpace-stdout.txt new file mode 100644 index 000000000..72addd794 --- /dev/null +++ b/Tests/RunCMake/Syntax/ParenNoSpace-stdout.txt @@ -0,0 +1,2 @@ +-- unquoted\(unquoted\) +-- quoted\(quoted\) diff --git a/Tests/RunCMake/Syntax/ParenNoSpace.cmake b/Tests/RunCMake/Syntax/ParenNoSpace.cmake new file mode 100644 index 000000000..c690d964e --- /dev/null +++ b/Tests/RunCMake/Syntax/ParenNoSpace.cmake @@ -0,0 +1,2 @@ +message(STATUS unquoted(unquoted)) +message(STATUS "quoted"("quoted")) diff --git a/Tests/RunCMake/Syntax/RunCMakeTest.cmake b/Tests/RunCMake/Syntax/RunCMakeTest.cmake new file mode 100644 index 000000000..94963f348 --- /dev/null +++ b/Tests/RunCMake/Syntax/RunCMakeTest.cmake @@ -0,0 +1,18 @@ +include(RunCMake) + +run_cmake(CommandSpaces) +run_cmake(CommandTabs) +run_cmake(CommandNewlines) +run_cmake(CommandComments) +run_cmake(CommandError0) +run_cmake(CommandError1) +run_cmake(String0) +run_cmake(String1) +run_cmake(StringNoSpace) +run_cmake(Unquoted0) +run_cmake(Unquoted1) +run_cmake(ParenNoSpace) +run_cmake(UnterminatedCall1) +run_cmake(UnterminatedCall2) +run_cmake(UnterminatedString) +run_cmake(BracketWarn) diff --git a/Tests/RunCMake/Syntax/String0-stderr.txt b/Tests/RunCMake/Syntax/String0-stderr.txt new file mode 100644 index 000000000..8eea0695c --- /dev/null +++ b/Tests/RunCMake/Syntax/String0-stderr.txt @@ -0,0 +1 @@ +^1 2;3 4$ diff --git a/Tests/RunCMake/Syntax/String0.cmake b/Tests/RunCMake/Syntax/String0.cmake new file mode 100644 index 000000000..95281d73f --- /dev/null +++ b/Tests/RunCMake/Syntax/String0.cmake @@ -0,0 +1,2 @@ +set(var 2 3) +message("1 ${var} 4") diff --git a/Tests/RunCMake/Syntax/String1-stderr.txt b/Tests/RunCMake/Syntax/String1-stderr.txt new file mode 100644 index 000000000..07e98dae0 --- /dev/null +++ b/Tests/RunCMake/Syntax/String1-stderr.txt @@ -0,0 +1,3 @@ +^ + 1 \${var} 4 + $ diff --git a/Tests/RunCMake/Syntax/String1.cmake b/Tests/RunCMake/Syntax/String1.cmake new file mode 100644 index 000000000..a94c9ffdb --- /dev/null +++ b/Tests/RunCMake/Syntax/String1.cmake @@ -0,0 +1,3 @@ +message(" + 1 \${var} 4 + ") diff --git a/Tests/RunCMake/Syntax/StringNoSpace-stderr.txt b/Tests/RunCMake/Syntax/StringNoSpace-stderr.txt new file mode 100644 index 000000000..89c2d2ae5 --- /dev/null +++ b/Tests/RunCMake/Syntax/StringNoSpace-stderr.txt @@ -0,0 +1,19 @@ +CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): + Syntax Warning in cmake code at + + .*/Tests/RunCMake/Syntax/StringNoSpace.cmake:2:28 + + Argument not separated from preceding token by whitespace. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\) at CMakeLists.txt:3 \(include\): + Syntax Warning in cmake code at + + .*/Tests/RunCMake/Syntax/StringNoSpace.cmake:2:31 + + Argument not separated from preceding token by whitespace. +This warning is for project developers. Use -Wno-dev to suppress it. + +\[1 \${var} \\n 4\] +\[x\] +\[y\]$ diff --git a/Tests/RunCMake/Syntax/StringNoSpace.cmake b/Tests/RunCMake/Syntax/StringNoSpace.cmake new file mode 100644 index 000000000..76f22db9a --- /dev/null +++ b/Tests/RunCMake/Syntax/StringNoSpace.cmake @@ -0,0 +1,4 @@ +# Quoted arguments may be immediately followed by another argument. +foreach(x "1 \${var} \\n 4""x"y) + message("[${x}]") +endforeach() diff --git a/Tests/RunCMake/Syntax/Unquoted0-stderr.txt b/Tests/RunCMake/Syntax/Unquoted0-stderr.txt new file mode 100644 index 000000000..ea68ebfa9 --- /dev/null +++ b/Tests/RunCMake/Syntax/Unquoted0-stderr.txt @@ -0,0 +1 @@ +^1234$ diff --git a/Tests/RunCMake/Syntax/Unquoted0.cmake b/Tests/RunCMake/Syntax/Unquoted0.cmake new file mode 100644 index 000000000..c5314c9f0 --- /dev/null +++ b/Tests/RunCMake/Syntax/Unquoted0.cmake @@ -0,0 +1,2 @@ +set(var 2 3) +message(1 ${var} 4) diff --git a/Tests/RunCMake/Syntax/Unquoted1-stderr.txt b/Tests/RunCMake/Syntax/Unquoted1-stderr.txt new file mode 100644 index 000000000..ff8194a6f --- /dev/null +++ b/Tests/RunCMake/Syntax/Unquoted1-stderr.txt @@ -0,0 +1 @@ +^\[\]\[=\]\[\$\$\(MV\)-DSTR=" \[="\[;\]$ diff --git a/Tests/RunCMake/Syntax/Unquoted1.cmake b/Tests/RunCMake/Syntax/Unquoted1.cmake new file mode 100644 index 000000000..0344fbd59 --- /dev/null +++ b/Tests/RunCMake/Syntax/Unquoted1.cmake @@ -0,0 +1 @@ +message([] [=] [$ $(MV) -DSTR=" [=" [;]) diff --git a/Tests/RunCMake/Syntax/UnterminatedCall1-result.txt b/Tests/RunCMake/Syntax/UnterminatedCall1-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/Syntax/UnterminatedCall1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/UnterminatedCall1-stderr.txt b/Tests/RunCMake/Syntax/UnterminatedCall1-stderr.txt new file mode 100644 index 000000000..281ce0da8 --- /dev/null +++ b/Tests/RunCMake/Syntax/UnterminatedCall1-stderr.txt @@ -0,0 +1,7 @@ +CMake Error: Error in cmake code at +.*/Syntax/UnterminatedCall1.cmake:2: +Parse error. Function missing ending "\)". End of file reached. +CMake Error at CMakeLists.txt:3 \(include\): + include could not find load file: + + UnterminatedCall1.cmake diff --git a/Tests/RunCMake/Syntax/UnterminatedCall1.cmake b/Tests/RunCMake/Syntax/UnterminatedCall1.cmake new file mode 100644 index 000000000..1166109c9 --- /dev/null +++ b/Tests/RunCMake/Syntax/UnterminatedCall1.cmake @@ -0,0 +1 @@ +message( diff --git a/Tests/RunCMake/Syntax/UnterminatedCall2-result.txt b/Tests/RunCMake/Syntax/UnterminatedCall2-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/Syntax/UnterminatedCall2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/UnterminatedCall2-stderr.txt b/Tests/RunCMake/Syntax/UnterminatedCall2-stderr.txt new file mode 100644 index 000000000..065de30fc --- /dev/null +++ b/Tests/RunCMake/Syntax/UnterminatedCall2-stderr.txt @@ -0,0 +1,7 @@ +CMake Error: Error in cmake code at +.*/Syntax/UnterminatedCall2.cmake:4: +Parse error. Function missing ending "\)". End of file reached. +CMake Error at CMakeLists.txt:3 \(include\): + include could not find load file: + + UnterminatedCall2.cmake diff --git a/Tests/RunCMake/Syntax/UnterminatedCall2.cmake b/Tests/RunCMake/Syntax/UnterminatedCall2.cmake new file mode 100644 index 000000000..26e9e6223 --- /dev/null +++ b/Tests/RunCMake/Syntax/UnterminatedCall2.cmake @@ -0,0 +1,3 @@ +set(var "\ +") +message( diff --git a/Tests/RunCMake/Syntax/UnterminatedString-result.txt b/Tests/RunCMake/Syntax/UnterminatedString-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/Syntax/UnterminatedString-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/UnterminatedString-stderr.txt b/Tests/RunCMake/Syntax/UnterminatedString-stderr.txt new file mode 100644 index 000000000..d9250328d --- /dev/null +++ b/Tests/RunCMake/Syntax/UnterminatedString-stderr.txt @@ -0,0 +1,8 @@ +CMake Error: Error in cmake code at +.*/Syntax/UnterminatedString.cmake:2: +Parse error. Function missing ending "\)". Instead found unterminated string with text "\) +". +CMake Error at CMakeLists.txt:3 \(include\): + include could not find load file: + + UnterminatedString.cmake$ diff --git a/Tests/RunCMake/Syntax/UnterminatedString.cmake b/Tests/RunCMake/Syntax/UnterminatedString.cmake new file mode 100644 index 000000000..721ae7510 --- /dev/null +++ b/Tests/RunCMake/Syntax/UnterminatedString.cmake @@ -0,0 +1 @@ +set(var ") diff --git a/Tests/RunCMake/TargetPolicies/CMakeLists.txt b/Tests/RunCMake/TargetPolicies/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/TargetPolicies/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-result.txt b/Tests/RunCMake/TargetPolicies/PolicyList-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/TargetPolicies/PolicyList-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt new file mode 100644 index 000000000..6533b75d8 --- /dev/null +++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt @@ -0,0 +1,13 @@ + Error evaluating generator expression: + + \$<TARGET_POLICY:NOT_A_POLICY> + + \$<TARGET_POLICY:prop> may only be used with a limited number of policies. + Currently it may be used with the following policies: + + \* CMP0003 + \* CMP0004 + \* CMP0008 + \* CMP0020 + \* CMP0021 + \* CMP0022 diff --git a/Tests/RunCMake/TargetPolicies/PolicyList.cmake b/Tests/RunCMake/TargetPolicies/PolicyList.cmake new file mode 100644 index 000000000..c290b65a6 --- /dev/null +++ b/Tests/RunCMake/TargetPolicies/PolicyList.cmake @@ -0,0 +1,8 @@ + +enable_language(CXX) + +add_library(empty empty.cpp) +target_compile_definitions(empty + PRIVATE + $<$<TARGET_POLICY:NOT_A_POLICY>:SOME_DEFINE> +) diff --git a/Tests/RunCMake/TargetPolicies/RunCMakeTest.cmake b/Tests/RunCMake/TargetPolicies/RunCMakeTest.cmake new file mode 100644 index 000000000..7a9463050 --- /dev/null +++ b/Tests/RunCMake/TargetPolicies/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(PolicyList) diff --git a/Tests/RunCMake/TargetPolicies/empty.cpp b/Tests/RunCMake/TargetPolicies/empty.cpp new file mode 100644 index 000000000..7279c5e0b --- /dev/null +++ b/Tests/RunCMake/TargetPolicies/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty(void) +{ + return 0; +} diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt index 3b3bab07d..3adf73ea0 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget-stderr.txt @@ -1,8 +1,8 @@ CMake Error at BadNonTarget.cmake:7 \(include_directories\): Error evaluating generator expression: - \$<TARGET_PROPERTY:NonExistant,INCLUDE_DIRECTORIES> + \$<TARGET_PROPERTY:NonExistent,INCLUDE_DIRECTORIES> - Target "NonExistant" not found. + Target "NonExistent" not found. Call Stack \(most recent call first\): CMakeLists.txt:8 \(include\)$ diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget.cmake index b020c0821..97d81e9f1 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget.cmake +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadNonTarget.cmake @@ -4,4 +4,4 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp" add_executable(TargetPropertyGeneratorExpressions "${CMAKE_CURRENT_BINARY_DIR}/main.cpp") -include_directories("$<TARGET_PROPERTY:NonExistant,INCLUDE_DIRECTORIES>") +include_directories("$<TARGET_PROPERTY:NonExistent,INCLUDE_DIRECTORIES>") diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt index 22577da4a..90afc127e 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} CXX) # MSVC creates extra targets which pollute the stderr unless we set this. diff --git a/Tests/RunCMake/VisibilityPreset/CMakeLists.txt b/Tests/RunCMake/VisibilityPreset/CMakeLists.txt new file mode 100644 index 000000000..90afc127e --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/CMakeLists.txt @@ -0,0 +1,8 @@ + +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} CXX) + +# MSVC creates extra targets which pollute the stderr unless we set this. +set(CMAKE_SUPPRESS_REGENERATION TRUE) + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/VisibilityPreset/PropertyTypo-result.txt b/Tests/RunCMake/VisibilityPreset/PropertyTypo-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/PropertyTypo-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/VisibilityPreset/PropertyTypo-stderr.txt b/Tests/RunCMake/VisibilityPreset/PropertyTypo-stderr.txt new file mode 100644 index 000000000..ca8c33f36 --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/PropertyTypo-stderr.txt @@ -0,0 +1 @@ +CMake Error: Target visibility_preset uses unsupported value \"hiden\" for CXX_VISIBILITY_PRESET diff --git a/Tests/RunCMake/VisibilityPreset/PropertyTypo.cmake b/Tests/RunCMake/VisibilityPreset/PropertyTypo.cmake new file mode 100644 index 000000000..03c0ed9a2 --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/PropertyTypo.cmake @@ -0,0 +1,3 @@ + +add_library(visibility_preset SHARED lib.cpp) +set_property(TARGET visibility_preset PROPERTY CXX_VISIBILITY_PRESET hiden) diff --git a/Tests/RunCMake/VisibilityPreset/RunCMakeTest.cmake b/Tests/RunCMake/VisibilityPreset/RunCMakeTest.cmake new file mode 100644 index 000000000..2d7883208 --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(PropertyTypo) diff --git a/Tests/RunCMake/VisibilityPreset/lib.cpp b/Tests/RunCMake/VisibilityPreset/lib.cpp new file mode 100644 index 000000000..06b3472f2 --- /dev/null +++ b/Tests/RunCMake/VisibilityPreset/lib.cpp @@ -0,0 +1,5 @@ + +int foo(void) +{ + return 42; +} diff --git a/Tests/RunCMake/add_dependencies/CMakeLists.txt b/Tests/RunCMake/add_dependencies/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/add_dependencies/CMakeLists.txt +++ b/Tests/RunCMake/add_dependencies/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/alias_targets/CMakeLists.txt b/Tests/RunCMake/alias_targets/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/alias_targets/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/alias_targets/RunCMakeTest.cmake b/Tests/RunCMake/alias_targets/RunCMakeTest.cmake new file mode 100644 index 000000000..9a5eaaf1c --- /dev/null +++ b/Tests/RunCMake/alias_targets/RunCMakeTest.cmake @@ -0,0 +1,20 @@ +include(RunCMake) + +run_cmake(no-targets) +run_cmake(multiple-targets) +run_cmake(exclude-from-all) +run_cmake(imported) +run_cmake(invalid-name) +run_cmake(invalid-target) +run_cmake(imported-target) +run_cmake(alias-target) +run_cmake(set_property) +run_cmake(set_target_properties) +run_cmake(target_link_libraries) +run_cmake(target_include_directories) +run_cmake(export) +run_cmake(install-export) +run_cmake(name-conflict) +run_cmake(add_dependencies) +run_cmake(add_executable-library) +run_cmake(add_library-executable) diff --git a/Tests/RunCMake/alias_targets/add_dependencies-result.txt b/Tests/RunCMake/alias_targets/add_dependencies-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/add_dependencies-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/add_dependencies-stderr.txt b/Tests/RunCMake/alias_targets/add_dependencies-stderr.txt new file mode 100644 index 000000000..53f248741 --- /dev/null +++ b/Tests/RunCMake/alias_targets/add_dependencies-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at add_dependencies.cmake:9 \(add_dependencies\): + Cannot add target-level dependencies to alias target "alias". + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/add_dependencies.cmake b/Tests/RunCMake/alias_targets/add_dependencies.cmake new file mode 100644 index 000000000..7436371a2 --- /dev/null +++ b/Tests/RunCMake/alias_targets/add_dependencies.cmake @@ -0,0 +1,9 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) +add_library(bar empty.cpp) + +add_library(alias ALIAS foo) + +add_dependencies(alias bar) diff --git a/Tests/RunCMake/alias_targets/add_executable-library-result.txt b/Tests/RunCMake/alias_targets/add_executable-library-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/add_executable-library-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/add_executable-library-stderr.txt b/Tests/RunCMake/alias_targets/add_executable-library-stderr.txt new file mode 100644 index 000000000..eb22b3dbe --- /dev/null +++ b/Tests/RunCMake/alias_targets/add_executable-library-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at add_executable-library.cmake:6 \(add_executable\): + add_executable cannot create ALIAS target "alias" because target "foo" is + not an executable. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/add_executable-library.cmake b/Tests/RunCMake/alias_targets/add_executable-library.cmake new file mode 100644 index 000000000..e30f112d8 --- /dev/null +++ b/Tests/RunCMake/alias_targets/add_executable-library.cmake @@ -0,0 +1,6 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) + +add_executable(alias ALIAS foo) diff --git a/Tests/RunCMake/alias_targets/add_library-executable-result.txt b/Tests/RunCMake/alias_targets/add_library-executable-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/add_library-executable-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/add_library-executable-stderr.txt b/Tests/RunCMake/alias_targets/add_library-executable-stderr.txt new file mode 100644 index 000000000..ee290e441 --- /dev/null +++ b/Tests/RunCMake/alias_targets/add_library-executable-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at add_library-executable.cmake:6 \(add_library\): + add_library cannot create ALIAS target "alias" because target "foo" is not + a library. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/add_library-executable.cmake b/Tests/RunCMake/alias_targets/add_library-executable.cmake new file mode 100644 index 000000000..22457a9b7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/add_library-executable.cmake @@ -0,0 +1,6 @@ + +enable_language(CXX) + +add_executable(foo empty.cpp) + +add_library(alias ALIAS foo) diff --git a/Tests/RunCMake/alias_targets/alias-target-result.txt b/Tests/RunCMake/alias_targets/alias-target-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/alias-target-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/alias-target-stderr.txt b/Tests/RunCMake/alias_targets/alias-target-stderr.txt new file mode 100644 index 000000000..eae227a25 --- /dev/null +++ b/Tests/RunCMake/alias_targets/alias-target-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at alias-target.cmake:8 \(add_library\): + add_library cannot create ALIAS target "next_alias" because target "alias" + is itself an ALIAS. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/alias-target.cmake b/Tests/RunCMake/alias_targets/alias-target.cmake new file mode 100644 index 000000000..0b8da6014 --- /dev/null +++ b/Tests/RunCMake/alias_targets/alias-target.cmake @@ -0,0 +1,8 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) + +add_library(alias ALIAS foo) + +add_library(next_alias ALIAS alias) diff --git a/Tests/RunCMake/alias_targets/empty.cpp b/Tests/RunCMake/alias_targets/empty.cpp new file mode 100644 index 000000000..bfbbddeb9 --- /dev/null +++ b/Tests/RunCMake/alias_targets/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/alias_targets/exclude-from-all-result.txt b/Tests/RunCMake/alias_targets/exclude-from-all-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/exclude-from-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/exclude-from-all-stderr.txt b/Tests/RunCMake/alias_targets/exclude-from-all-stderr.txt new file mode 100644 index 000000000..fce15d384 --- /dev/null +++ b/Tests/RunCMake/alias_targets/exclude-from-all-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at exclude-from-all.cmake:6 \(add_library\): + add_library EXCLUDE_FROM_ALL with ALIAS makes no sense. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/exclude-from-all.cmake b/Tests/RunCMake/alias_targets/exclude-from-all.cmake new file mode 100644 index 000000000..0091918fe --- /dev/null +++ b/Tests/RunCMake/alias_targets/exclude-from-all.cmake @@ -0,0 +1,6 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) + +add_library(alias ALIAS EXCLUDE_FROM_ALL foo) diff --git a/Tests/RunCMake/alias_targets/export-result.txt b/Tests/RunCMake/alias_targets/export-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/export-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/export-stderr.txt b/Tests/RunCMake/alias_targets/export-stderr.txt new file mode 100644 index 000000000..848b9840c --- /dev/null +++ b/Tests/RunCMake/alias_targets/export-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at export.cmake:8 \(export\): + export given ALIAS target "alias" which may not be exported. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/export.cmake b/Tests/RunCMake/alias_targets/export.cmake new file mode 100644 index 000000000..dd84a80da --- /dev/null +++ b/Tests/RunCMake/alias_targets/export.cmake @@ -0,0 +1,8 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) + +add_library(alias ALIAS foo) + +export(TARGETS alias FILE someFile.cmake) diff --git a/Tests/RunCMake/alias_targets/imported-result.txt b/Tests/RunCMake/alias_targets/imported-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/imported-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/imported-stderr.txt b/Tests/RunCMake/alias_targets/imported-stderr.txt new file mode 100644 index 000000000..b905847f2 --- /dev/null +++ b/Tests/RunCMake/alias_targets/imported-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at imported.cmake:2 \(add_library\): + add_library IMPORTED with ALIAS is not allowed. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/imported-target-result.txt b/Tests/RunCMake/alias_targets/imported-target-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/imported-target-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/imported-target-stderr.txt b/Tests/RunCMake/alias_targets/imported-target-stderr.txt new file mode 100644 index 000000000..bbff29a80 --- /dev/null +++ b/Tests/RunCMake/alias_targets/imported-target-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at imported-target.cmake:6 \(add_library\): + add_library cannot create ALIAS target "alias" because target "foo" is + IMPORTED. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/imported-target.cmake b/Tests/RunCMake/alias_targets/imported-target.cmake new file mode 100644 index 000000000..7259ab091 --- /dev/null +++ b/Tests/RunCMake/alias_targets/imported-target.cmake @@ -0,0 +1,6 @@ + +enable_language(CXX) + +add_library(foo SHARED IMPORTED) + +add_library(alias ALIAS foo) diff --git a/Tests/RunCMake/alias_targets/imported.cmake b/Tests/RunCMake/alias_targets/imported.cmake new file mode 100644 index 000000000..6a605911a --- /dev/null +++ b/Tests/RunCMake/alias_targets/imported.cmake @@ -0,0 +1,2 @@ + +add_library(alias IMPORTED ALIAS) diff --git a/Tests/RunCMake/alias_targets/install-export-result.txt b/Tests/RunCMake/alias_targets/install-export-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/install-export-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/install-export-stderr.txt b/Tests/RunCMake/alias_targets/install-export-stderr.txt new file mode 100644 index 000000000..3c3c0edd6 --- /dev/null +++ b/Tests/RunCMake/alias_targets/install-export-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at install-export.cmake:8 \(install\): + install TARGETS given target "alias" which is an alias. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/install-export.cmake b/Tests/RunCMake/alias_targets/install-export.cmake new file mode 100644 index 000000000..b1c6a4f4d --- /dev/null +++ b/Tests/RunCMake/alias_targets/install-export.cmake @@ -0,0 +1,9 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) + +add_library(alias ALIAS foo) + +install(TARGETS alias EXPORT theTargets DESTINATION prefix) +install(EXPORT theTargets DESTINATION lib/cmake) diff --git a/Tests/RunCMake/alias_targets/invalid-name-result.txt b/Tests/RunCMake/alias_targets/invalid-name-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/invalid-name-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/invalid-name-stderr.txt b/Tests/RunCMake/alias_targets/invalid-name-stderr.txt new file mode 100644 index 000000000..d33b57c10 --- /dev/null +++ b/Tests/RunCMake/alias_targets/invalid-name-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at invalid-name.cmake:6 \(add_library\): + add_library Invalid name for ALIAS: invalid\$name +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/invalid-name.cmake b/Tests/RunCMake/alias_targets/invalid-name.cmake new file mode 100644 index 000000000..bbd39e3b6 --- /dev/null +++ b/Tests/RunCMake/alias_targets/invalid-name.cmake @@ -0,0 +1,6 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) + +add_library(invalid$name ALIAS foo) diff --git a/Tests/RunCMake/alias_targets/invalid-target-result.txt b/Tests/RunCMake/alias_targets/invalid-target-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/invalid-target-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/invalid-target-stderr.txt b/Tests/RunCMake/alias_targets/invalid-target-stderr.txt new file mode 100644 index 000000000..342d488b9 --- /dev/null +++ b/Tests/RunCMake/alias_targets/invalid-target-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at invalid-target.cmake:2 \(add_library\): + add_library cannot create ALIAS target "alias" because target "foo" does + not already exist. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/invalid-target.cmake b/Tests/RunCMake/alias_targets/invalid-target.cmake new file mode 100644 index 000000000..c43da6162 --- /dev/null +++ b/Tests/RunCMake/alias_targets/invalid-target.cmake @@ -0,0 +1,2 @@ + +add_library(alias ALIAS foo) diff --git a/Tests/RunCMake/alias_targets/multiple-targets-result.txt b/Tests/RunCMake/alias_targets/multiple-targets-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/multiple-targets-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/multiple-targets-stderr.txt b/Tests/RunCMake/alias_targets/multiple-targets-stderr.txt new file mode 100644 index 000000000..596f404e4 --- /dev/null +++ b/Tests/RunCMake/alias_targets/multiple-targets-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at multiple-targets.cmake:7 \(add_library\): + add_library ALIAS requires exactly one target argument. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/multiple-targets.cmake b/Tests/RunCMake/alias_targets/multiple-targets.cmake new file mode 100644 index 000000000..811eb7a53 --- /dev/null +++ b/Tests/RunCMake/alias_targets/multiple-targets.cmake @@ -0,0 +1,7 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) +add_library(bar empty.cpp) + +add_library(alias ALIAS foo bar) diff --git a/Tests/RunCMake/alias_targets/name-conflict-result.txt b/Tests/RunCMake/alias_targets/name-conflict-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/name-conflict-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/name-conflict-stderr.txt b/Tests/RunCMake/alias_targets/name-conflict-stderr.txt new file mode 100644 index 000000000..3c0faa9df --- /dev/null +++ b/Tests/RunCMake/alias_targets/name-conflict-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at name-conflict.cmake:8 \(add_library\): + add_library cannot create target "bar" because an alias with the same name + already exists. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/name-conflict.cmake b/Tests/RunCMake/alias_targets/name-conflict.cmake new file mode 100644 index 000000000..d21a09248 --- /dev/null +++ b/Tests/RunCMake/alias_targets/name-conflict.cmake @@ -0,0 +1,8 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) + +add_library(bar ALIAS foo) + +add_library(bar empty.cpp) diff --git a/Tests/RunCMake/alias_targets/no-targets-result.txt b/Tests/RunCMake/alias_targets/no-targets-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/no-targets-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/no-targets-stderr.txt b/Tests/RunCMake/alias_targets/no-targets-stderr.txt new file mode 100644 index 000000000..cdf7e577c --- /dev/null +++ b/Tests/RunCMake/alias_targets/no-targets-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at no-targets.cmake:4 \(add_library\): + add_library ALIAS requires exactly one target argument. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/no-targets.cmake b/Tests/RunCMake/alias_targets/no-targets.cmake new file mode 100644 index 000000000..a5c5ee501 --- /dev/null +++ b/Tests/RunCMake/alias_targets/no-targets.cmake @@ -0,0 +1,4 @@ + +enable_language(CXX) + +add_library(alias ALIAS) diff --git a/Tests/RunCMake/alias_targets/set_property-result.txt b/Tests/RunCMake/alias_targets/set_property-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/set_property-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/set_property-stderr.txt b/Tests/RunCMake/alias_targets/set_property-stderr.txt new file mode 100644 index 000000000..e85aa568c --- /dev/null +++ b/Tests/RunCMake/alias_targets/set_property-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at set_property.cmake:8 \(set_property\): + set_property can not be used on an ALIAS target. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/set_property.cmake b/Tests/RunCMake/alias_targets/set_property.cmake new file mode 100644 index 000000000..1f5e475c4 --- /dev/null +++ b/Tests/RunCMake/alias_targets/set_property.cmake @@ -0,0 +1,8 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) + +add_library(alias ALIAS foo) + +set_property(TARGET alias PROPERTY ANYTHING 1) diff --git a/Tests/RunCMake/alias_targets/set_target_properties-result.txt b/Tests/RunCMake/alias_targets/set_target_properties-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/set_target_properties-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/set_target_properties-stderr.txt b/Tests/RunCMake/alias_targets/set_target_properties-stderr.txt new file mode 100644 index 000000000..8922c0d3e --- /dev/null +++ b/Tests/RunCMake/alias_targets/set_target_properties-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at set_target_properties.cmake:8 \(set_target_properties\): + set_target_properties can not be used on an ALIAS target. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/set_target_properties.cmake b/Tests/RunCMake/alias_targets/set_target_properties.cmake new file mode 100644 index 000000000..ee44d4595 --- /dev/null +++ b/Tests/RunCMake/alias_targets/set_target_properties.cmake @@ -0,0 +1,8 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) + +add_library(alias ALIAS foo) + +set_target_properties(alias PROPERTIES ANYTHING 1) diff --git a/Tests/RunCMake/alias_targets/target_include_directories-result.txt b/Tests/RunCMake/alias_targets/target_include_directories-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/target_include_directories-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/target_include_directories-stderr.txt b/Tests/RunCMake/alias_targets/target_include_directories-stderr.txt new file mode 100644 index 000000000..b8903b245 --- /dev/null +++ b/Tests/RunCMake/alias_targets/target_include_directories-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at target_include_directories.cmake:8 \(target_include_directories\): + target_include_directories can not be used on an ALIAS target. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/target_include_directories.cmake b/Tests/RunCMake/alias_targets/target_include_directories.cmake new file mode 100644 index 000000000..c26830e11 --- /dev/null +++ b/Tests/RunCMake/alias_targets/target_include_directories.cmake @@ -0,0 +1,8 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) + +add_library(alias ALIAS foo) + +target_include_directories(alias PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>) diff --git a/Tests/RunCMake/alias_targets/target_link_libraries-result.txt b/Tests/RunCMake/alias_targets/target_link_libraries-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/alias_targets/target_link_libraries-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/alias_targets/target_link_libraries-stderr.txt b/Tests/RunCMake/alias_targets/target_link_libraries-stderr.txt new file mode 100644 index 000000000..2d7ff20da --- /dev/null +++ b/Tests/RunCMake/alias_targets/target_link_libraries-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at target_link_libraries.cmake:9 \(target_link_libraries\): + target_link_libraries can not be used on an ALIAS target. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/alias_targets/target_link_libraries.cmake b/Tests/RunCMake/alias_targets/target_link_libraries.cmake new file mode 100644 index 000000000..b7b9e6018 --- /dev/null +++ b/Tests/RunCMake/alias_targets/target_link_libraries.cmake @@ -0,0 +1,9 @@ + +enable_language(CXX) + +add_library(foo empty.cpp) +add_library(bar empty.cpp) + +add_library(alias ALIAS foo) + +target_link_libraries(alias bar) diff --git a/Tests/RunCMake/build_command/CMakeLists.txt b/Tests/RunCMake/build_command/CMakeLists.txt index f6e84c04d..73e6a785a 100644 --- a/Tests/RunCMake/build_command/CMakeLists.txt +++ b/Tests/RunCMake/build_command/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) if(NOT NoProject) project(${RunCMake_TEST} NONE) endif() diff --git a/Tests/RunCMake/find_package/CMakeLists.txt b/Tests/RunCMake/find_package/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/find_package/CMakeLists.txt +++ b/Tests/RunCMake/find_package/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/get_filename_component/CMakeLists.txt b/Tests/RunCMake/get_filename_component/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/get_filename_component/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/get_filename_component/KnownComponents.cmake b/Tests/RunCMake/get_filename_component/KnownComponents.cmake new file mode 100644 index 000000000..9d7cf9079 --- /dev/null +++ b/Tests/RunCMake/get_filename_component/KnownComponents.cmake @@ -0,0 +1,38 @@ +macro(check desc actual expect) + if(NOT "x${actual}" STREQUAL "x${expect}") + message(SEND_ERROR "${desc}: got \"${actual}\", not \"${expect}\"") + endif() +endmacro() + +set(filename "/path/to/filename.ext.in") +set(expect_DIRECTORY "/path/to") +set(expect_NAME "filename.ext.in") +set(expect_EXT ".ext.in") +set(expect_NAME_WE "filename") +set(expect_PATH "/path/to") +foreach(c DIRECTORY NAME EXT NAME_WE PATH) + get_filename_component(actual_${c} "${filename}" ${c}) + check("${c}" "${actual_${c}}" "${expect_${c}}") +endforeach() + +get_filename_component(test_slashes "c:\\path\\to\\filename.ext.in" DIRECTORY) +check("DIRECTORY from backslashes" "${test_slashes}" "c:/path/to") + +get_filename_component(test_winroot "c:\\filename.ext.in" DIRECTORY) +check("DIRECTORY in windows root" "${test_winroot}" "c:/") + +get_filename_component(test_absolute "/path/to/a/../filename.ext.in" ABSOLUTE) +check("ABSOLUTE" "${test_absolute}" "/path/to/filename.ext.in") + +get_filename_component(test_absolute "/../path/to/filename.ext.in" ABSOLUTE) +check("ABSOLUTE .. in root" "${test_absolute}" "/path/to/filename.ext.in") +get_filename_component(test_absolute "c:/../path/to/filename.ext.in" ABSOLUTE) +check("ABSOLUTE .. in windows root" "${test_absolute}" "c:/path/to/filename.ext.in") + +get_filename_component(test_cache "/path/to/filename.ext.in" DIRECTORY CACHE) +check("CACHE 1" "${test_cache}" "/path/to") +get_filename_component(test_cache "/path/to/other/filename.ext.in" DIRECTORY CACHE) +check("CACHE 2" "${test_cache}" "/path/to") +unset(test_cache CACHE) +get_filename_component(test_cache "/path/to/other/filename.ext.in" DIRECTORY CACHE) +check("CACHE 3" "${test_cache}" "/path/to/other") diff --git a/Tests/RunCMake/get_filename_component/RunCMakeTest.cmake b/Tests/RunCMake/get_filename_component/RunCMakeTest.cmake new file mode 100644 index 000000000..156fc8f3c --- /dev/null +++ b/Tests/RunCMake/get_filename_component/RunCMakeTest.cmake @@ -0,0 +1,4 @@ +include(RunCMake) + +run_cmake(KnownComponents) +run_cmake(UnknownComponent) diff --git a/Tests/RunCMake/get_filename_component/UnknownComponent-result.txt b/Tests/RunCMake/get_filename_component/UnknownComponent-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/get_filename_component/UnknownComponent-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/get_filename_component/UnknownComponent-stderr.txt b/Tests/RunCMake/get_filename_component/UnknownComponent-stderr.txt new file mode 100644 index 000000000..b146e5b4b --- /dev/null +++ b/Tests/RunCMake/get_filename_component/UnknownComponent-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at UnknownComponent.cmake:1 \(get_filename_component\): + get_filename_component unknown component BOGUS +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/get_filename_component/UnknownComponent.cmake b/Tests/RunCMake/get_filename_component/UnknownComponent.cmake new file mode 100644 index 000000000..06abc51e6 --- /dev/null +++ b/Tests/RunCMake/get_filename_component/UnknownComponent.cmake @@ -0,0 +1 @@ +get_filename_component(var "/path/to/filename.ext.in" BOGUS) diff --git a/Tests/RunCMake/if/CMakeLists.txt b/Tests/RunCMake/if/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/if/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/if/IsDirectory-stdout.txt b/Tests/RunCMake/if/IsDirectory-stdout.txt new file mode 100644 index 000000000..b89446a65 --- /dev/null +++ b/Tests/RunCMake/if/IsDirectory-stdout.txt @@ -0,0 +1 @@ +CMAKE_CURRENT_SOURCE_DIR exists, tested with trailing slash diff --git a/Tests/RunCMake/if/IsDirectory.cmake b/Tests/RunCMake/if/IsDirectory.cmake new file mode 100644 index 000000000..23d126dd4 --- /dev/null +++ b/Tests/RunCMake/if/IsDirectory.cmake @@ -0,0 +1,5 @@ +if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/") + message(STATUS "CMAKE_CURRENT_SOURCE_DIR exists, tested with trailing slash") +else() + message(FATAL_ERROR "CMAKE_CURRENT_SOURCE_DIR does not exist!") +endif() diff --git a/Tests/RunCMake/if/IsDirectoryLong-stdout.txt b/Tests/RunCMake/if/IsDirectoryLong-stdout.txt new file mode 100644 index 000000000..5e6275429 --- /dev/null +++ b/Tests/RunCMake/if/IsDirectoryLong-stdout.txt @@ -0,0 +1 @@ +Directory path with length 94208 correctly does not exist. diff --git a/Tests/RunCMake/if/IsDirectoryLong.cmake b/Tests/RunCMake/if/IsDirectoryLong.cmake new file mode 100644 index 000000000..0e93be744 --- /dev/null +++ b/Tests/RunCMake/if/IsDirectoryLong.cmake @@ -0,0 +1,10 @@ +set(d "/long/path/to/directory") +foreach(i RANGE 11) + set(d "${d}${d}") +endforeach() +string(LENGTH "${d}" dl) +if(IS_DIRECTORY "${d}/") + message(FATAL_ERROR "Directory should not exist!") +else() + message(STATUS "Directory path with length ${dl} correctly does not exist.") +endif() diff --git a/Tests/RunCMake/if/RunCMakeTest.cmake b/Tests/RunCMake/if/RunCMakeTest.cmake new file mode 100644 index 000000000..6b6b74b54 --- /dev/null +++ b/Tests/RunCMake/if/RunCMakeTest.cmake @@ -0,0 +1,4 @@ +include(RunCMake) + +run_cmake(IsDirectory) +run_cmake(IsDirectoryLong) diff --git a/Tests/RunCMake/include/CMakeLists.txt b/Tests/RunCMake/include/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/include/CMakeLists.txt +++ b/Tests/RunCMake/include/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/include_directories/CMP0021-result.txt b/Tests/RunCMake/include_directories/CMP0021-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/include_directories/CMP0021-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/include_directories/CMP0021-stderr.txt b/Tests/RunCMake/include_directories/CMP0021-stderr.txt new file mode 100644 index 000000000..c0781e7cf --- /dev/null +++ b/Tests/RunCMake/include_directories/CMP0021-stderr.txt @@ -0,0 +1,4 @@ +CMake Error in CMakeLists.txt: + Found relative path while evaluating include directories of "userTarget": + + "foo" diff --git a/Tests/RunCMake/include_directories/CMP0021.cmake b/Tests/RunCMake/include_directories/CMP0021.cmake new file mode 100644 index 000000000..f18666b07 --- /dev/null +++ b/Tests/RunCMake/include_directories/CMP0021.cmake @@ -0,0 +1,9 @@ +enable_language(CXX) + +cmake_policy(SET CMP0021 NEW) + +add_library(testTarget "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp") +set_property(TARGET testTarget PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<1:foo>") + +add_library(userTarget "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp") +target_include_directories(userTarget PRIVATE $<TARGET_PROPERTY:testTarget,INTERFACE_INCLUDE_DIRECTORIES>) diff --git a/Tests/RunCMake/include_directories/CMakeLists.txt b/Tests/RunCMake/include_directories/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/include_directories/CMakeLists.txt +++ b/Tests/RunCMake/include_directories/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt b/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt index 63aec9052..71e6456f3 100644 --- a/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt +++ b/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt @@ -42,3 +42,12 @@ CMake Debug Log at DebugIncludes.cmake:30 \(target_link_libraries\): Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) ++ +CMake Debug Log at DebugIncludes.cmake:55 \(set_property\): + Used includes for target lll: + + \* .*/Tests/RunCMake/include_directories/nine + \* .*/Tests/RunCMake/include_directories/ten + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/include_directories/DebugIncludes.cmake b/Tests/RunCMake/include_directories/DebugIncludes.cmake index de3689956..bbc9e4602 100644 --- a/Tests/RunCMake/include_directories/DebugIncludes.cmake +++ b/Tests/RunCMake/include_directories/DebugIncludes.cmake @@ -45,3 +45,11 @@ function(some_function) endfunction() some_function() + +add_library(bar "${CMAKE_CURRENT_BINARY_DIR}/DebugIncludes.cpp") +target_include_directories(bar + INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/nine" + "${CMAKE_CURRENT_SOURCE_DIR}/ten" +) +set_property(TARGET lll APPEND PROPERTY LINK_LIBRARIES bar) diff --git a/Tests/RunCMake/include_directories/RunCMakeTest.cmake b/Tests/RunCMake/include_directories/RunCMakeTest.cmake index f5160860d..f0704f462 100644 --- a/Tests/RunCMake/include_directories/RunCMakeTest.cmake +++ b/Tests/RunCMake/include_directories/RunCMakeTest.cmake @@ -8,3 +8,5 @@ run_cmake(BinaryDirectoryInInterface) run_cmake(RelativePathInInterface) run_cmake(ImportedTarget) run_cmake(RelativePathInGenex) +run_cmake(CMP0021) +run_cmake(install_config) diff --git a/Tests/RunCMake/include_directories/install_config-result.txt b/Tests/RunCMake/include_directories/install_config-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/include_directories/install_config-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/include_directories/install_config-stderr.txt b/Tests/RunCMake/include_directories/install_config-stderr.txt new file mode 100644 index 000000000..ac7b7b0ec --- /dev/null +++ b/Tests/RunCMake/include_directories/install_config-stderr.txt @@ -0,0 +1,5 @@ +CMake Error in CMakeLists.txt: + Target "foo" is installed with INCLUDES DESTINATION set to a context + sensitive path. Paths which depend on the configuration, policy values or + the link interface are not supported. Consider using + target_include_directories instead. diff --git a/Tests/RunCMake/include_directories/install_config.cmake b/Tests/RunCMake/include_directories/install_config.cmake new file mode 100644 index 000000000..46c626c70 --- /dev/null +++ b/Tests/RunCMake/include_directories/install_config.cmake @@ -0,0 +1,6 @@ + +enable_language(CXX) + +add_executable(foo empty.cpp) +install(TARGETS foo EXPORT fooTargets DESTINATION . INCLUDES DESTINATION include/$<CONFIGURATION>) +install(EXPORT fooTargets DESTINATION lib/cmake) diff --git a/Tests/RunCMake/include_external_msproject/CMakeLists.txt b/Tests/RunCMake/include_external_msproject/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/include_external_msproject/CMakeLists.txt +++ b/Tests/RunCMake/include_external_msproject/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/list/CMakeLists.txt b/Tests/RunCMake/list/CMakeLists.txt index e8db6b05b..12cd3c775 100644 --- a/Tests/RunCMake/list/CMakeLists.txt +++ b/Tests/RunCMake/list/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/target_link_libraries/CMP0023-NEW-2-result.txt b/Tests/RunCMake/target_link_libraries/CMP0023-NEW-2-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0023-NEW-2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/target_link_libraries/CMP0023-NEW-2-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0023-NEW-2-stderr.txt new file mode 100644 index 000000000..d27686d4b --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0023-NEW-2-stderr.txt @@ -0,0 +1,16 @@ +CMake Error at CMP0023-NEW-2.cmake:11 \(target_link_libraries\): + Policy CMP0023 is not set: Plain and keyword target_link_libraries + signatures cannot be mixed. Run "cmake --help-policy CMP0023" for policy + details. Use the cmake_policy command to set the policy and suppress this + warning. + + The plain signature for target_link_libraries has already been used with + the target "foo". All uses of target_link_libraries with a target must be + either all-keyword or all-plain. + + The uses of the plain signature are here: + + \* CMP0023-NEW-2.cmake:10 \(target_link_libraries\) + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/target_link_libraries/CMP0023-NEW-2.cmake b/Tests/RunCMake/target_link_libraries/CMP0023-NEW-2.cmake new file mode 100644 index 000000000..f8b354690 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0023-NEW-2.cmake @@ -0,0 +1,11 @@ + +project(CMP0022-WARN) + +cmake_policy(SET CMP0023 NEW) + +add_library(foo SHARED empty_vs6_1.cpp) +add_library(bar SHARED empty_vs6_2.cpp) +add_library(bat SHARED empty_vs6_3.cpp) + +target_link_libraries(foo bar) +target_link_libraries(foo LINK_PRIVATE bat) diff --git a/Tests/RunCMake/target_link_libraries/CMP0023-NEW-result.txt b/Tests/RunCMake/target_link_libraries/CMP0023-NEW-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0023-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/target_link_libraries/CMP0023-NEW-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0023-NEW-stderr.txt new file mode 100644 index 000000000..d7be0ff38 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0023-NEW-stderr.txt @@ -0,0 +1,16 @@ +CMake Error at CMP0023-NEW.cmake:11 \(target_link_libraries\): + Policy CMP0023 is not set: Plain and keyword target_link_libraries + signatures cannot be mixed. Run "cmake --help-policy CMP0023" for policy + details. Use the cmake_policy command to set the policy and suppress this + warning. + + The plain signature for target_link_libraries has already been used with + the target "foo". All uses of target_link_libraries with a target must be + either all-keyword or all-plain. + + The uses of the plain signature are here: + + \* CMP0023-NEW.cmake:10 \(target_link_libraries\) + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/target_link_libraries/CMP0023-NEW.cmake b/Tests/RunCMake/target_link_libraries/CMP0023-NEW.cmake new file mode 100644 index 000000000..f0aa63fbd --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0023-NEW.cmake @@ -0,0 +1,11 @@ + +project(CMP0022-WARN) + +cmake_policy(SET CMP0023 NEW) + +add_library(foo SHARED empty_vs6_1.cpp) +add_library(bar SHARED empty_vs6_2.cpp) +add_library(bat SHARED empty_vs6_3.cpp) + +target_link_libraries(foo bar) +target_link_libraries(foo PRIVATE bat) diff --git a/Tests/RunCMake/target_link_libraries/CMP0023-WARN-2-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0023-WARN-2-stderr.txt new file mode 100644 index 000000000..514786154 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0023-WARN-2-stderr.txt @@ -0,0 +1,16 @@ +CMake Warning \(dev\) at CMP0023-WARN-2.cmake:9 \(target_link_libraries\): + Policy CMP0023 is not set: Plain and keyword target_link_libraries + signatures cannot be mixed. Run "cmake --help-policy CMP0023" for policy + details. Use the cmake_policy command to set the policy and suppress this + warning. + + The plain signature for target_link_libraries has already been used with + the target "foo". All uses of target_link_libraries with a target should + be either all-keyword or all-plain. + + The uses of the plain signature are here: + + \* CMP0023-WARN-2.cmake:8 \(target_link_libraries\) + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/target_link_libraries/CMP0023-WARN-2.cmake b/Tests/RunCMake/target_link_libraries/CMP0023-WARN-2.cmake new file mode 100644 index 000000000..2e9cba82c --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0023-WARN-2.cmake @@ -0,0 +1,9 @@ + +project(CMP0022-WARN) + +add_library(foo SHARED empty_vs6_1.cpp) +add_library(bar SHARED empty_vs6_2.cpp) +add_library(bat SHARED empty_vs6_3.cpp) + +target_link_libraries(foo bar) +target_link_libraries(foo LINK_PRIVATE bat) diff --git a/Tests/RunCMake/target_link_libraries/CMP0023-WARN-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0023-WARN-stderr.txt new file mode 100644 index 000000000..a7474fac9 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0023-WARN-stderr.txt @@ -0,0 +1,16 @@ +CMake Warning \(dev\) at CMP0023-WARN.cmake:9 \(target_link_libraries\): + Policy CMP0023 is not set: Plain and keyword target_link_libraries + signatures cannot be mixed. Run "cmake --help-policy CMP0023" for policy + details. Use the cmake_policy command to set the policy and suppress this + warning. + + The plain signature for target_link_libraries has already been used with + the target "foo". All uses of target_link_libraries with a target should + be either all-keyword or all-plain. + + The uses of the plain signature are here: + + \* CMP0023-WARN.cmake:8 \(target_link_libraries\) + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/target_link_libraries/CMP0023-WARN.cmake b/Tests/RunCMake/target_link_libraries/CMP0023-WARN.cmake new file mode 100644 index 000000000..fcc8da03e --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMP0023-WARN.cmake @@ -0,0 +1,9 @@ + +project(CMP0022-WARN) + +add_library(foo SHARED empty_vs6_1.cpp) +add_library(bar SHARED empty_vs6_2.cpp) +add_library(bat SHARED empty_vs6_3.cpp) + +target_link_libraries(foo bar) +target_link_libraries(foo PRIVATE bat) diff --git a/Tests/RunCMake/target_link_libraries/CMakeLists.txt b/Tests/RunCMake/target_link_libraries/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/target_link_libraries/MixedSignature-result.txt b/Tests/RunCMake/target_link_libraries/MixedSignature-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/MixedSignature-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/target_link_libraries/MixedSignature-stderr.txt b/Tests/RunCMake/target_link_libraries/MixedSignature-stderr.txt new file mode 100644 index 000000000..a0c66dbe2 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/MixedSignature-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at MixedSignature.cmake:6 \(target_link_libraries\): + The PUBLIC or PRIVATE option must appear as the second argument, just after + the target name. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/target_link_libraries/MixedSignature.cmake b/Tests/RunCMake/target_link_libraries/MixedSignature.cmake new file mode 100644 index 000000000..fa7068584 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/MixedSignature.cmake @@ -0,0 +1,6 @@ + +add_library(foo empty_vs6_1.cpp) +add_library(bar empty_vs6_2.cpp) +add_library(bat empty_vs6_3.cpp) + +target_link_libraries(foo LINK_PUBLIC bar PRIVATE bat) diff --git a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake new file mode 100644 index 000000000..f97022e1b --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake @@ -0,0 +1,8 @@ +include(RunCMake) + +run_cmake(CMP0023-WARN) +run_cmake(CMP0023-NEW) +run_cmake(CMP0023-WARN-2) +run_cmake(CMP0023-NEW-2) +run_cmake(MixedSignature) +run_cmake(Separate-PRIVATE-LINK_PRIVATE-uses) diff --git a/Tests/RunCMake/target_link_libraries/Separate-PRIVATE-LINK_PRIVATE-uses-result.txt b/Tests/RunCMake/target_link_libraries/Separate-PRIVATE-LINK_PRIVATE-uses-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/Separate-PRIVATE-LINK_PRIVATE-uses-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/target_link_libraries/Separate-PRIVATE-LINK_PRIVATE-uses.cmake b/Tests/RunCMake/target_link_libraries/Separate-PRIVATE-LINK_PRIVATE-uses.cmake new file mode 100644 index 000000000..e32891d6d --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/Separate-PRIVATE-LINK_PRIVATE-uses.cmake @@ -0,0 +1,9 @@ + +enable_language(CXX) + +add_library(foo empty_vs6_1.cpp) +add_library(bar empty_vs6_2.cpp) +add_library(bat empty_vs6_3.cpp) + +target_link_libraries(foo LINK_PRIVATE bar) +target_link_libraries(foo PRIVATE bat) diff --git a/Tests/RunCMake/target_link_libraries/empty.cpp b/Tests/RunCMake/target_link_libraries/empty.cpp new file mode 100644 index 000000000..bfbbddeb9 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/target_link_libraries/empty_vs6_1.cpp b/Tests/RunCMake/target_link_libraries/empty_vs6_1.cpp new file mode 100644 index 000000000..7efedabfa --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/empty_vs6_1.cpp @@ -0,0 +1 @@ +#include "empty.cpp" diff --git a/Tests/RunCMake/target_link_libraries/empty_vs6_2.cpp b/Tests/RunCMake/target_link_libraries/empty_vs6_2.cpp new file mode 100644 index 000000000..7efedabfa --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/empty_vs6_2.cpp @@ -0,0 +1 @@ +#include "empty.cpp" diff --git a/Tests/RunCMake/target_link_libraries/empty_vs6_3.cpp b/Tests/RunCMake/target_link_libraries/empty_vs6_3.cpp new file mode 100644 index 000000000..7efedabfa --- /dev/null +++ b/Tests/RunCMake/target_link_libraries/empty_vs6_3.cpp @@ -0,0 +1 @@ +#include "empty.cpp" diff --git a/Tests/RunCMake/try_compile/BadLinkLibraries-result.txt b/Tests/RunCMake/try_compile/BadLinkLibraries-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/BadLinkLibraries-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt b/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt new file mode 100644 index 000000000..eceffecc8 --- /dev/null +++ b/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at BadLinkLibraries.cmake:2 \(try_compile\): + Only libraries may be used as try_compile IMPORTED LINK_LIBRARIES. Got + not_a_library of type UTILITY. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/BadLinkLibraries.cmake b/Tests/RunCMake/try_compile/BadLinkLibraries.cmake new file mode 100644 index 000000000..e8b5add87 --- /dev/null +++ b/Tests/RunCMake/try_compile/BadLinkLibraries.cmake @@ -0,0 +1,3 @@ +add_custom_target(not_a_library) +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + LINK_LIBRARIES not_a_library) diff --git a/Tests/RunCMake/try_compile/BadSources1-result.txt b/Tests/RunCMake/try_compile/BadSources1-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/BadSources1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/BadSources1-stderr.txt b/Tests/RunCMake/try_compile/BadSources1-stderr.txt new file mode 100644 index 000000000..864a2942c --- /dev/null +++ b/Tests/RunCMake/try_compile/BadSources1-stderr.txt @@ -0,0 +1,12 @@ +CMake Error at BadSources1.cmake:1 \(try_compile\): + Unknown extension ".c" for file + + .*/Tests/RunCMake/try_compile/src.c + + try_compile\(\) works only for enabled languages. Currently these are: + + NONE + + See project\(\) command to enable other languages. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/BadSources1.cmake b/Tests/RunCMake/try_compile/BadSources1.cmake new file mode 100644 index 000000000..aa4dc5ee5 --- /dev/null +++ b/Tests/RunCMake/try_compile/BadSources1.cmake @@ -0,0 +1 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c) diff --git a/Tests/RunCMake/try_compile/BadSources2-result.txt b/Tests/RunCMake/try_compile/BadSources2-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/BadSources2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/BadSources2-stderr.txt b/Tests/RunCMake/try_compile/BadSources2-stderr.txt new file mode 100644 index 000000000..3313f9933 --- /dev/null +++ b/Tests/RunCMake/try_compile/BadSources2-stderr.txt @@ -0,0 +1,12 @@ +CMake Error at BadSources2.cmake:2 \(try_compile\): + Unknown extension ".cxx" for file + + .*/Tests/RunCMake/try_compile/src.cxx + + try_compile\(\) works only for enabled languages. Currently these are: + + C NONE( RC)? + + See project\(\) command to enable other languages. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/BadSources2.cmake b/Tests/RunCMake/try_compile/BadSources2.cmake new file mode 100644 index 000000000..ed2b0364d --- /dev/null +++ b/Tests/RunCMake/try_compile/BadSources2.cmake @@ -0,0 +1,5 @@ +enable_language(C) +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c + ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx + ) diff --git a/Tests/RunCMake/try_compile/CMakeLists.txt b/Tests/RunCMake/try_compile/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/try_compile/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-result.txt b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt new file mode 100644 index 000000000..5d09c0c61 --- /dev/null +++ b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at CopyFileErrorNoCopyFile.cmake:1 \(try_compile\): + COPY_FILE_ERROR may be used only with COPY_FILE +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake new file mode 100644 index 000000000..8d7cb0e7f --- /dev/null +++ b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake @@ -0,0 +1,2 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE_ERROR _copied) diff --git a/Tests/RunCMake/try_compile/NoArgs-result.txt b/Tests/RunCMake/try_compile/NoArgs-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoArgs-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NoArgs-stderr.txt b/Tests/RunCMake/try_compile/NoArgs-stderr.txt new file mode 100644 index 000000000..8808fd19a --- /dev/null +++ b/Tests/RunCMake/try_compile/NoArgs-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NoArgs.cmake:1 \(try_compile\): + try_compile unknown error. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoArgs.cmake b/Tests/RunCMake/try_compile/NoArgs.cmake new file mode 100644 index 000000000..8f751d9a2 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoArgs.cmake @@ -0,0 +1 @@ +try_compile() diff --git a/Tests/RunCMake/try_compile/NoCopyFile-result.txt b/Tests/RunCMake/try_compile/NoCopyFile-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFile-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt new file mode 100644 index 000000000..d65d94883 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NoCopyFile.cmake:1 \(try_compile\): + COPY_FILE must be followed by a file path +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoCopyFile.cmake b/Tests/RunCMake/try_compile/NoCopyFile.cmake new file mode 100644 index 000000000..8c648ff32 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFile.cmake @@ -0,0 +1,2 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE) diff --git a/Tests/RunCMake/try_compile/NoCopyFile2-result.txt b/Tests/RunCMake/try_compile/NoCopyFile2-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFile2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt new file mode 100644 index 000000000..e88952475 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NoCopyFile2.cmake:1 \(try_compile\): + COPY_FILE must be followed by a file path +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoCopyFile2.cmake b/Tests/RunCMake/try_compile/NoCopyFile2.cmake new file mode 100644 index 000000000..04b7f6882 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFile2.cmake @@ -0,0 +1,2 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE CMAKE_FLAGS -DA=B) diff --git a/Tests/RunCMake/try_compile/NoCopyFileError-result.txt b/Tests/RunCMake/try_compile/NoCopyFileError-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFileError-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt new file mode 100644 index 000000000..ed552fd8e --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NoCopyFileError.cmake:1 \(try_compile\): + COPY_FILE_ERROR must be followed by a variable name +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoCopyFileError.cmake b/Tests/RunCMake/try_compile/NoCopyFileError.cmake new file mode 100644 index 000000000..d4d69ee01 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCopyFileError.cmake @@ -0,0 +1,2 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/copied.bin COPY_FILE_ERROR) diff --git a/Tests/RunCMake/try_compile/NoOutputVariable-result.txt b/Tests/RunCMake/try_compile/NoOutputVariable-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoOutputVariable-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt b/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt new file mode 100644 index 000000000..18ad751cf --- /dev/null +++ b/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NoOutputVariable.cmake:1 \(try_compile\): + OUTPUT_VARIABLE must be followed by a variable name +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoOutputVariable.cmake b/Tests/RunCMake/try_compile/NoOutputVariable.cmake new file mode 100644 index 000000000..3b9cb345b --- /dev/null +++ b/Tests/RunCMake/try_compile/NoOutputVariable.cmake @@ -0,0 +1,2 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + OUTPUT_VARIABLE) diff --git a/Tests/RunCMake/try_compile/NoOutputVariable2-result.txt b/Tests/RunCMake/try_compile/NoOutputVariable2-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoOutputVariable2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt b/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt new file mode 100644 index 000000000..8b2cc254c --- /dev/null +++ b/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NoOutputVariable2.cmake:1 \(try_compile\): + OUTPUT_VARIABLE must be followed by a variable name +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoOutputVariable2.cmake b/Tests/RunCMake/try_compile/NoOutputVariable2.cmake new file mode 100644 index 000000000..ad9ac9ac5 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoOutputVariable2.cmake @@ -0,0 +1,2 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + OUTPUT_VARIABLE CMAKE_FLAGS -DA=B) diff --git a/Tests/RunCMake/try_compile/NoSources-result.txt b/Tests/RunCMake/try_compile/NoSources-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoSources-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NoSources-stderr.txt b/Tests/RunCMake/try_compile/NoSources-stderr.txt new file mode 100644 index 000000000..023032b60 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoSources-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NoSources.cmake:1 \(try_compile\): + SOURCES must be followed by at least one source file +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoSources.cmake b/Tests/RunCMake/try_compile/NoSources.cmake new file mode 100644 index 000000000..8a73af42c --- /dev/null +++ b/Tests/RunCMake/try_compile/NoSources.cmake @@ -0,0 +1 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} SOURCES) diff --git a/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-result.txt b/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt b/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt new file mode 100644 index 000000000..025e65868 --- /dev/null +++ b/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NonSourceCompileDefinitions.cmake:1 \(try_compile\): + COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NonSourceCompileDefinitions.cmake b/Tests/RunCMake/try_compile/NonSourceCompileDefinitions.cmake new file mode 100644 index 000000000..8eb0d47a0 --- /dev/null +++ b/Tests/RunCMake/try_compile/NonSourceCompileDefinitions.cmake @@ -0,0 +1,2 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/proj + TestProject COMPILE_DEFINITIONS DEF) diff --git a/Tests/RunCMake/try_compile/NonSourceCopyFile-result.txt b/Tests/RunCMake/try_compile/NonSourceCopyFile-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/NonSourceCopyFile-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt b/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt new file mode 100644 index 000000000..f5893e19f --- /dev/null +++ b/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at NonSourceCopyFile.cmake:1 \(try_compile\): + COPY_FILE specified on a srcdir type TRY_COMPILE +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NonSourceCopyFile.cmake b/Tests/RunCMake/try_compile/NonSourceCopyFile.cmake new file mode 100644 index 000000000..c44192f9e --- /dev/null +++ b/Tests/RunCMake/try_compile/NonSourceCopyFile.cmake @@ -0,0 +1,2 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/proj + TestProject COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/result) diff --git a/Tests/RunCMake/try_compile/OneArg-result.txt b/Tests/RunCMake/try_compile/OneArg-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/OneArg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/OneArg-stderr.txt b/Tests/RunCMake/try_compile/OneArg-stderr.txt new file mode 100644 index 000000000..12835bed6 --- /dev/null +++ b/Tests/RunCMake/try_compile/OneArg-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at OneArg.cmake:1 \(try_compile\): + try_compile unknown error. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/OneArg.cmake b/Tests/RunCMake/try_compile/OneArg.cmake new file mode 100644 index 000000000..e60a46207 --- /dev/null +++ b/Tests/RunCMake/try_compile/OneArg.cmake @@ -0,0 +1 @@ +try_compile(RESULT) diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake new file mode 100644 index 000000000..c93445876 --- /dev/null +++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake @@ -0,0 +1,17 @@ +include(RunCMake) + +run_cmake(CopyFileErrorNoCopyFile) +run_cmake(NoArgs) +run_cmake(OneArg) +run_cmake(TwoArgs) +run_cmake(NoCopyFile) +run_cmake(NoCopyFile2) +run_cmake(NoCopyFileError) +run_cmake(NoOutputVariable) +run_cmake(NoOutputVariable2) +run_cmake(NoSources) +run_cmake(BadLinkLibraries) +run_cmake(BadSources1) +run_cmake(BadSources2) +run_cmake(NonSourceCopyFile) +run_cmake(NonSourceCompileDefinitions) diff --git a/Tests/RunCMake/try_compile/TwoArgs-result.txt b/Tests/RunCMake/try_compile/TwoArgs-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/try_compile/TwoArgs-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/TwoArgs-stderr.txt b/Tests/RunCMake/try_compile/TwoArgs-stderr.txt new file mode 100644 index 000000000..b9c08fc9d --- /dev/null +++ b/Tests/RunCMake/try_compile/TwoArgs-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at TwoArgs.cmake:1 \(try_compile\): + try_compile unknown error. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/TwoArgs.cmake b/Tests/RunCMake/try_compile/TwoArgs.cmake new file mode 100644 index 000000000..7f2212d62 --- /dev/null +++ b/Tests/RunCMake/try_compile/TwoArgs.cmake @@ -0,0 +1 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/Tests/RunCMake/try_compile/proj/CMakeLists.txt b/Tests/RunCMake/try_compile/proj/CMakeLists.txt new file mode 100644 index 000000000..78a87c016 --- /dev/null +++ b/Tests/RunCMake/try_compile/proj/CMakeLists.txt @@ -0,0 +1,2 @@ +cmake_minimum_required(VERSION 2.8.10) +project(TestProject NONE) diff --git a/Tests/RunCMake/try_compile/src.c b/Tests/RunCMake/try_compile/src.c new file mode 100644 index 000000000..78f2de106 --- /dev/null +++ b/Tests/RunCMake/try_compile/src.c @@ -0,0 +1 @@ +int main(void) { return 0; } diff --git a/Tests/RunCMake/variable_watch/CMakeLists.txt b/Tests/RunCMake/variable_watch/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/variable_watch/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/variable_watch/ModifiedAccess-stderr.txt b/Tests/RunCMake/variable_watch/ModifiedAccess-stderr.txt new file mode 100644 index 000000000..3ff96fcc3 --- /dev/null +++ b/Tests/RunCMake/variable_watch/ModifiedAccess-stderr.txt @@ -0,0 +1,4 @@ +CMake Debug Log at ModifiedAccess.cmake:3 \(set\): + Variable "b" was accessed using MODIFIED_ACCESS with value "b". +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\)$ diff --git a/Tests/RunCMake/variable_watch/ModifiedAccess.cmake b/Tests/RunCMake/variable_watch/ModifiedAccess.cmake new file mode 100644 index 000000000..87943b39f --- /dev/null +++ b/Tests/RunCMake/variable_watch/ModifiedAccess.cmake @@ -0,0 +1,3 @@ +set(b "a") +variable_watch(b) +set(b "b") diff --git a/Tests/RunCMake/variable_watch/NoWatcher-stderr.txt b/Tests/RunCMake/variable_watch/NoWatcher-stderr.txt new file mode 100644 index 000000000..d2994297d --- /dev/null +++ b/Tests/RunCMake/variable_watch/NoWatcher-stderr.txt @@ -0,0 +1,5 @@ +my_func +CMake Debug Log at NoWatcher.cmake:8 \(set\): + Variable "b" was accessed using MODIFIED_ACCESS with value "". +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\)$ diff --git a/Tests/RunCMake/variable_watch/NoWatcher.cmake b/Tests/RunCMake/variable_watch/NoWatcher.cmake new file mode 100644 index 000000000..8a68efbe4 --- /dev/null +++ b/Tests/RunCMake/variable_watch/NoWatcher.cmake @@ -0,0 +1,8 @@ +function(my_func) + message("my_func") +endfunction() +variable_watch(a my_func) +set(a "") + +variable_watch(b) +set(b "") diff --git a/Tests/RunCMake/variable_watch/RunCMakeTest.cmake b/Tests/RunCMake/variable_watch/RunCMakeTest.cmake new file mode 100644 index 000000000..9becb4cd7 --- /dev/null +++ b/Tests/RunCMake/variable_watch/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(ModifiedAccess) +run_cmake(NoWatcher) +run_cmake(WatchTwice) diff --git a/Tests/RunCMake/variable_watch/WatchTwice-stderr.txt b/Tests/RunCMake/variable_watch/WatchTwice-stderr.txt new file mode 100644 index 000000000..fa7d3472a --- /dev/null +++ b/Tests/RunCMake/variable_watch/WatchTwice-stderr.txt @@ -0,0 +1,2 @@ +From watch1 +From watch2 diff --git a/Tests/RunCMake/variable_watch/WatchTwice.cmake b/Tests/RunCMake/variable_watch/WatchTwice.cmake new file mode 100644 index 000000000..540cfc160 --- /dev/null +++ b/Tests/RunCMake/variable_watch/WatchTwice.cmake @@ -0,0 +1,11 @@ +function (watch1) + message("From watch1") +endfunction () + +function (watch2) + message("From watch2") +endfunction () + +variable_watch(watched watch1) +variable_watch(watched watch2) +set(access "${watched}") diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt index 479d6ec36..b969bfdf0 100644 --- a/Tests/SimpleInstall/CMakeLists.txt +++ b/Tests/SimpleInstall/CMakeLists.txt @@ -122,7 +122,7 @@ if(STAGE2) RESULT_VARIABLE SAMPLE_SCRIPT_RESULT OUTPUT_VARIABLE SAMPLE_SCRIPT_OUTPUT ) - if(NOT "${SAMPLE_SCRIPT_RESULT}" MATCHES "^0$") + if(NOT "${SAMPLE_SCRIPT_RESULT}" STREQUAL "0") message(FATAL_ERROR "Sample script [${CUR_SCRIPT}] failed: [${SAMPLE_SCRIPT_RESULT}]") endif() diff --git a/Tests/SimpleInstallS2/CMakeLists.txt b/Tests/SimpleInstallS2/CMakeLists.txt index 479d6ec36..b969bfdf0 100644 --- a/Tests/SimpleInstallS2/CMakeLists.txt +++ b/Tests/SimpleInstallS2/CMakeLists.txt @@ -122,7 +122,7 @@ if(STAGE2) RESULT_VARIABLE SAMPLE_SCRIPT_RESULT OUTPUT_VARIABLE SAMPLE_SCRIPT_OUTPUT ) - if(NOT "${SAMPLE_SCRIPT_RESULT}" MATCHES "^0$") + if(NOT "${SAMPLE_SCRIPT_RESULT}" STREQUAL "0") message(FATAL_ERROR "Sample script [${CUR_SCRIPT}] failed: [${SAMPLE_SCRIPT_RESULT}]") endif() diff --git a/Tests/StringFileTest/CMakeLists.txt b/Tests/StringFileTest/CMakeLists.txt index 6d798b067..00383ab37 100644 --- a/Tests/StringFileTest/CMakeLists.txt +++ b/Tests/StringFileTest/CMakeLists.txt @@ -280,3 +280,9 @@ endif() if(NOT ST_NINE STREQUAL "9") message(SEND_ERROR "SUBSTRING does not return the tail when selected with -1") endif() + +string(MAKE_C_IDENTIFIER "1one-two$" MCI_1) + +if(NOT MCI_1 STREQUAL _1one_two_) + message(SEND_ERROR "MAKE_C_IDENTIFIER did not create expected result.") +endif() diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt index b6b66d8ee..a4d949006 100644 --- a/Tests/TryCompile/CMakeLists.txt +++ b/Tests/TryCompile/CMakeLists.txt @@ -44,6 +44,23 @@ else() file(REMOVE "${TryCompile_BINARY_DIR}/CopyOfPass") endif() +# try to compile a file that should compile +# also check that COPY_FILE_ERROR works +file(WRITE ${TryCompile_BINARY_DIR}/invalid "") +try_compile(SHOULD_PASS + ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp + ${TryCompile_SOURCE_DIR}/pass.c + OUTPUT_VARIABLE TRY_OUT + COPY_FILE ${TryCompile_BINARY_DIR}/invalid/path + COPY_FILE_ERROR _captured + ) +if(NOT SHOULD_PASS) + message(SEND_ERROR "should pass failed ${TRY_OUT}") +endif() +if(NOT _captured MATCHES "Cannot copy output executable.*/invalid/path") + message(SEND_ERROR "COPY_FILE_ERROR did not capture expected message") +endif() + # try to compile a file that should not compile try_compile(SHOULD_FAIL ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp @@ -71,6 +88,42 @@ if(SHOULD_FAIL) message(SEND_ERROR "Should fail passed ${TRY_OUT}") endif() +# try to compile two files that should compile +try_compile(SHOULD_PASS + ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp + SOURCES ${TryCompile_SOURCE_DIR}/pass2a.c ${TryCompile_SOURCE_DIR}/pass2b.cxx + OUTPUT_VARIABLE TRY_OUT) +if(NOT SHOULD_PASS) + message(SEND_ERROR "should pass failed ${TRY_OUT}") +endif() + +# try to compile two files that should not compile +try_compile(SHOULD_FAIL + ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp + SOURCES ${TryCompile_SOURCE_DIR}/fail2a.c ${TryCompile_SOURCE_DIR}/fail2b.c + OUTPUT_VARIABLE TRY_OUT) +if(SHOULD_FAIL) + message(SEND_ERROR "Should fail passed ${TRY_OUT}") +endif() + +# try to compile a file that should compile +set(_c_flags "${CMAKE_C_FLAGS}") +if(CMAKE_GENERATOR STREQUAL "Visual Studio 6") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D \"TESTDEF\"") +elseif(WATCOM) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -dTESTDEF") +else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \"-DTESTDEF\"") +endif() +try_compile(SHOULD_PASS + ${TryCompile_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp + ${TryCompile_SOURCE_DIR}/testdef.c + OUTPUT_VARIABLE TRY_OUT) +if(NOT SHOULD_PASS) + message(SEND_ERROR "should pass failed ${TRY_OUT}") +endif() +set(CMAKE_C_FLAGS "${_c_flags}") + if(NOT SHOULD_FAIL) if(SHOULD_PASS) message("All Tests passed, ignore all previous output.") diff --git a/Tests/TryCompile/fail2a.c b/Tests/TryCompile/fail2a.c new file mode 100644 index 000000000..78f2de106 --- /dev/null +++ b/Tests/TryCompile/fail2a.c @@ -0,0 +1 @@ +int main(void) { return 0; } diff --git a/Tests/TryCompile/fail2b.c b/Tests/TryCompile/fail2b.c new file mode 100644 index 000000000..5ee809c04 --- /dev/null +++ b/Tests/TryCompile/fail2b.c @@ -0,0 +1 @@ +does_not_compile diff --git a/Tests/TryCompile/pass2a.c b/Tests/TryCompile/pass2a.c new file mode 100644 index 000000000..bbfe6d581 --- /dev/null +++ b/Tests/TryCompile/pass2a.c @@ -0,0 +1,2 @@ +extern int pass2b(void); +int main() { return pass2b(); } diff --git a/Tests/TryCompile/pass2b.cxx b/Tests/TryCompile/pass2b.cxx new file mode 100644 index 000000000..4c539e21d --- /dev/null +++ b/Tests/TryCompile/pass2b.cxx @@ -0,0 +1 @@ +extern "C" int pass2b(void) { return 0; } diff --git a/Tests/TryCompile/testdef.c b/Tests/TryCompile/testdef.c new file mode 100644 index 000000000..5401e7183 --- /dev/null +++ b/Tests/TryCompile/testdef.c @@ -0,0 +1,4 @@ +#ifndef TESTDEF +# error "TESTDEF should be defined!" +#endif +int main(void) { return 0; } diff --git a/Tests/VSProjectInSubdir/CMakeLists.txt b/Tests/VSProjectInSubdir/CMakeLists.txt new file mode 100644 index 000000000..c164a9798 --- /dev/null +++ b/Tests/VSProjectInSubdir/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.10) +project(VSProjectInSubdir NONE) +add_subdirectory(subdir) diff --git a/Tests/VSProjectInSubdir/subdir/CMakeLists.txt b/Tests/VSProjectInSubdir/subdir/CMakeLists.txt new file mode 100644 index 000000000..6c1b6a11a --- /dev/null +++ b/Tests/VSProjectInSubdir/subdir/CMakeLists.txt @@ -0,0 +1 @@ +add_custom_target(test COMMAND ${CMAKE_COMMAND} -E echo test VERBATIM) diff --git a/Tests/VSWindowsFormsResx/CMakeLists.txt b/Tests/VSWindowsFormsResx/CMakeLists.txt new file mode 100644 index 000000000..437381085 --- /dev/null +++ b/Tests/VSWindowsFormsResx/CMakeLists.txt @@ -0,0 +1,45 @@ +# +# Example CMakeLists.txt file to demonstrate how to make a designable Windows Forms project with CMake. +# +# Code modifications and example by John Farrier, john.farrier@helleboreconsulting.com +# + +cmake_minimum_required(VERSION 2.8.10) + +# Project Name +project(VSWindowsFormsResx CXX) + +include(CheckFunctionExists) +include(CheckCXXSourceCompiles) +include(CheckIncludeFile) + +# Note: The designable form is assumed to have a .h extension as is default in Visual Studio. +# Node: The designable form is assumed to have a .resx file with the same name and path (save extension) as is default in Visual Studio + +set(TARGET_H + WindowsFormsResx/MyForm.h + WindowsFormsResx/Header.h + ) + +set(TARGET_SRC + WindowsFormsResx/MyForm.cpp + WindowsFormsResx/Source.cpp + ) +set_source_files_properties(${TARGET_SRC} PROPERTIES COMPILE_FLAGS "/clr") + +set(TARGET_RESX + WindowsFormsResx/MyForm.resx + ) + +set(TARGET_LIBRARIES ${SYSLIBS}) +add_executable(${PROJECT_NAME} ${TARGET_SRC} ${TARGET_H} ${TARGET_RESX}) + +# Note: The property VS_GLOBAL_KEYWORD must be set. +set_property(TARGET ${PROJECT_NAME} PROPERTY VS_GLOBAL_KEYWORD "ManagedCProj") + +# Note: The property VS_DOTNET_REFERENCES must be set. +set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DOTNET_REFERENCES "System" "System.Data" "System.Drawing" "System.Windows.Forms" "System.Xml") + +# Note: Modification of compiler flags is required for CLR compatibility now that we are using .resx files. +string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") diff --git a/Tests/VSWindowsFormsResx/WindowsFormsResx/Header.h b/Tests/VSWindowsFormsResx/WindowsFormsResx/Header.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/Tests/VSWindowsFormsResx/WindowsFormsResx/Header.h diff --git a/Tests/VSWindowsFormsResx/WindowsFormsResx/MyForm.cpp b/Tests/VSWindowsFormsResx/WindowsFormsResx/MyForm.cpp new file mode 100644 index 000000000..154e268c7 --- /dev/null +++ b/Tests/VSWindowsFormsResx/WindowsFormsResx/MyForm.cpp @@ -0,0 +1 @@ +#include "MyForm.h"
\ No newline at end of file diff --git a/Tests/VSWindowsFormsResx/WindowsFormsResx/MyForm.h b/Tests/VSWindowsFormsResx/WindowsFormsResx/MyForm.h new file mode 100644 index 000000000..16222c5d4 --- /dev/null +++ b/Tests/VSWindowsFormsResx/WindowsFormsResx/MyForm.h @@ -0,0 +1,78 @@ +#pragma once + +namespace Farrier { + + using namespace System; + using namespace System::ComponentModel; + using namespace System::Collections; + using namespace System::Windows::Forms; + using namespace System::Data; + using namespace System::Drawing; + + /// <summary> + /// Summary for MyForm + /// </summary> + public ref class MyForm : public System::Windows::Forms::Form + { + public: + MyForm(void) + { + InitializeComponent(); + // + //TODO: Add the constructor code here + // + } + + protected: + /// <summary> + /// Clean up any resources being used. + /// </summary> + ~MyForm() + { + if (components) + { + delete components; + } + } + private: System::Windows::Forms::Button^ button1; + protected: + + private: + /// <summary> + /// Required designer variable. + /// </summary> + System::ComponentModel::Container ^components; + +#pragma region Windows Form Designer generated code + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + void InitializeComponent(void) + { + this->button1 = (gcnew System::Windows::Forms::Button()); + this->SuspendLayout(); + // + // button1 + // + this->button1->Location = System::Drawing::Point(13, 13); + this->button1->Name = L"button1"; + this->button1->Size = System::Drawing::Size(75, 23); + this->button1->TabIndex = 0; + this->button1->Text = L"button1"; + this->button1->UseVisualStyleBackColor = true; + // + // MyForm + // + this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); + this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; + this->ClientSize = System::Drawing::Size(284, 261); + this->Controls->Add(this->button1); + this->Name = L"MyForm"; + this->Text = L"MyForm"; + this->ResumeLayout(false); + + } +#pragma endregion + }; +} diff --git a/Tests/VSWindowsFormsResx/WindowsFormsResx/MyForm.resx b/Tests/VSWindowsFormsResx/WindowsFormsResx/MyForm.resx new file mode 100644 index 000000000..e8ae276d9 --- /dev/null +++ b/Tests/VSWindowsFormsResx/WindowsFormsResx/MyForm.resx @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root>
\ No newline at end of file diff --git a/Tests/VSWindowsFormsResx/WindowsFormsResx/Source.cpp b/Tests/VSWindowsFormsResx/WindowsFormsResx/Source.cpp new file mode 100644 index 000000000..aee9e2eb4 --- /dev/null +++ b/Tests/VSWindowsFormsResx/WindowsFormsResx/Source.cpp @@ -0,0 +1,4 @@ +int main(int argc, char **argv) +{ + return 0; +} diff --git a/Tests/WarnUnusedCliUnused/CMakeLists.txt b/Tests/WarnUnusedCliUnused/CMakeLists.txt new file mode 100644 index 000000000..7ed69bf3c --- /dev/null +++ b/Tests/WarnUnusedCliUnused/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 2.8) + +project(WarnUnusedCliUnused) + +set_directory_properties(PROPERTIES + ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_BINARY_DIR}/CMakeCache.txt" +) + +add_library(dummy empty.cpp) diff --git a/Tests/WarnUnusedCliUnused/empty.cpp b/Tests/WarnUnusedCliUnused/empty.cpp new file mode 100644 index 000000000..7279c5e0b --- /dev/null +++ b/Tests/WarnUnusedCliUnused/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty(void) +{ + return 0; +} diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index b8f6b3cb6..bad8d630e 100644 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -72,11 +72,11 @@ macro(ADD_DOCS target dependency) endmacro() # Help cmake-gui find the Qt DLLs on Windows. -set(WIN_SHELL_GENS "Visual Studio|NMake|MinGW|Watcom|Borland") -if(BUILD_QtDialog AND "${CMAKE_GENERATOR}" MATCHES "${WIN_SHELL_GENS}" - AND EXISTS "${QT_QMAKE_EXECUTABLE}" AND NOT CMAKE_NO_AUTO_QT_ENV) - get_filename_component(Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH) - if(EXISTS "${Qt_BIN_DIR}/QtCore4.dll") +if(TARGET cmake-gui) + get_property(Qt_BIN_DIR TARGET cmake-gui PROPERTY Qt_BIN_DIR) + set(WIN_SHELL_GENS "Visual Studio|NMake|MinGW|Watcom|Borland") + if(Qt_BIN_DIR AND "${CMAKE_GENERATOR}" MATCHES "${WIN_SHELL_GENS}" + AND NOT CMAKE_NO_AUTO_QT_ENV) # Tell the macro to set the path before running cmake-gui. string(REPLACE ";" "\\;" _PATH "PATH=${Qt_BIN_DIR};%PATH%") set(cmake-gui-PATH COMMAND set "${_PATH}") @@ -123,11 +123,12 @@ add_custom_command( MAIN_DEPENDENCY ${CMake_SOURCE_DIR}/Utilities/Doxygen/authors.txt ) -install_files(${CMAKE_MAN_DIR}/man1 FILES ${MAN_FILES}) -install_files(${CMAKE_DOC_DIR} FILES +install(FILES ${MAN_FILES} DESTINATION ${CMAKE_MAN_DIR}/man1) +install(FILES ${TEXT_FILES} ${HTML_FILES} ${DOCBOOK_FILES} + DESTINATION ${CMAKE_DOC_DIR} ) install(FILES cmake.m4 DESTINATION share/aclocal) diff --git a/Utilities/cmcompress/CMakeLists.txt b/Utilities/cmcompress/CMakeLists.txt index 3323dcd7d..806357327 100644 --- a/Utilities/cmcompress/CMakeLists.txt +++ b/Utilities/cmcompress/CMakeLists.txt @@ -2,4 +2,4 @@ PROJECT(CMCompress) ADD_LIBRARY(cmcompress cmcompress.c) -INSTALL(FILES Copyright.txt DESTINATION ${CMake_DOC_DEST}/cmcompress) +INSTALL(FILES Copyright.txt DESTINATION ${CMAKE_DOC_DIR}/cmcompress) diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt index 320612cf6..74a713dd8 100644 --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt @@ -716,7 +716,7 @@ TARGET_LINK_LIBRARIES(cmcurl ${CURL_LIBS}) IF(CMAKE_BUILD_CURL_SHARED) SET_TARGET_PROPERTIES(cmcurl PROPERTIES DEFINE_SYMBOL BUILDING_LIBCURL RUNTIME_OUTPUT_DIRECTORY ${CMake_BIN_DIR}) - INSTALL_TARGETS(/bin cmcurl) + INSTALL(TARGETS cmcurl RUNTIME DESTINATION bin) ENDIF(CMAKE_BUILD_CURL_SHARED) OPTION(CURL_TESTING "Do libCurl testing" OFF) @@ -731,4 +731,4 @@ IF(CMAKE_CURL_TEST_URL) ADD_TEST(curl LIBCURL ${CMAKE_CURL_TEST_URL}) ENDIF(CMAKE_CURL_TEST_URL) -INSTALL(FILES COPYING DESTINATION ${CMake_DOC_DEST}/cmcurl) +INSTALL(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmcurl) diff --git a/Utilities/cmcurl/Testing/sepheaders.c b/Utilities/cmcurl/Testing/sepheaders.c index 818578708..fc5b783bc 100644 --- a/Utilities/cmcurl/Testing/sepheaders.c +++ b/Utilities/cmcurl/Testing/sepheaders.c @@ -56,6 +56,7 @@ int main(int argc, char **argv) bodyfile = fopen(bodyfilename,"w"); if (bodyfile == NULL) { curl_easy_cleanup(curl_handle); + fclose(headerfile); return -1; } @@ -70,6 +71,7 @@ int main(int argc, char **argv) /* close the header file */ fclose(headerfile); + fclose(bodyfile); /* cleanup curl stuff */ curl_easy_cleanup(curl_handle); diff --git a/Utilities/cmcurl/Testing/simplessl.c b/Utilities/cmcurl/Testing/simplessl.c index 9a53603f4..e307eaa6f 100644 --- a/Utilities/cmcurl/Testing/simplessl.c +++ b/Utilities/cmcurl/Testing/simplessl.c @@ -114,5 +114,7 @@ int main(int argc, char **argv) curl_global_cleanup(); + if (headerfile) + fclose(headerfile); return 0; } diff --git a/Utilities/cmcurl/cookie.c b/Utilities/cmcurl/cookie.c index 2856ad882..d8ea24196 100644 --- a/Utilities/cmcurl/cookie.c +++ b/Utilities/cmcurl/cookie.c @@ -969,6 +969,8 @@ int Curl_cookie_output(struct CookieInfo *c, char *dumphere) format_ptr = get_netscape_format(co); if (format_ptr == NULL) { fprintf(out, "#\n# Fatal libcurl error\n"); + if(!use_stdout) + fclose(out); return 1; } fprintf(out, "%s\n", format_ptr); diff --git a/Utilities/cmcurl/ftp.c b/Utilities/cmcurl/ftp.c index 883988938..3ccbc4364 100644 --- a/Utilities/cmcurl/ftp.c +++ b/Utilities/cmcurl/ftp.c @@ -3683,7 +3683,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) /* seek out the next path component */ if (slash_pos-cur_pos) { /* we skip empty path components, like "x//y" since the FTP command - CWD requires a parameter and a non-existant parameter a) doesn't + CWD requires a parameter and a non-existent parameter a) doesn't work on many servers and b) has no effect on the others. */ int len = (int)(slash_pos - cur_pos + absolute_dir); ftpc->dirs[ftpc->dirdepth] = curl_easy_unescape(conn->data, diff --git a/Utilities/cmcurl/http.c b/Utilities/cmcurl/http.c index c07053bdd..5405aace1 100644 --- a/Utilities/cmcurl/http.c +++ b/Utilities/cmcurl/http.c @@ -178,7 +178,7 @@ static bool pickoneauth(struct auth *pick) picked = TRUE; /* The order of these checks is highly relevant, as this will be the order - of preference in case of the existance of multiple accepted types. */ + of preference in case of the existence of multiple accepted types. */ if(avail & CURLAUTH_GSSNEGOTIATE) pick->picked = CURLAUTH_GSSNEGOTIATE; else if(avail & CURLAUTH_DIGEST) diff --git a/Utilities/cmcurl/ssluse.c b/Utilities/cmcurl/ssluse.c index 14d05ac65..6709278fa 100644 --- a/Utilities/cmcurl/ssluse.c +++ b/Utilities/cmcurl/ssluse.c @@ -442,7 +442,7 @@ int cert_stuff(struct connectdata *conn, failf(data, "no key set to load from crypto engine\n"); return 0; } - /* the typecast below was added to please mingw32 */ + /* the typecast below was added to please MinGW32 */ priv_key = (EVP_PKEY *) ENGINE_load_private_key(conn->data->state.engine,key_file, #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS diff --git a/Utilities/cmcurl/urldata.h b/Utilities/cmcurl/urldata.h index 9537ce36b..46d956d1a 100644 --- a/Utilities/cmcurl/urldata.h +++ b/Utilities/cmcurl/urldata.h @@ -621,7 +621,7 @@ typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool); * Store's request specific data in the easy handle (SessionHandle). * Previously, these members were on the connectdata struct but since * a conn struct may now be shared between different SessionHandles, - * we store connection-specifc data here. + * we store connection-specific data here. * */ struct HandleData { diff --git a/Utilities/cmexpat/CMakeLists.txt b/Utilities/cmexpat/CMakeLists.txt index b75c11232..51ba413e5 100644 --- a/Utilities/cmexpat/CMakeLists.txt +++ b/Utilities/cmexpat/CMakeLists.txt @@ -31,4 +31,4 @@ CONFIGURE_FILE(${CMEXPAT_SOURCE_DIR}/expat.h ${CMEXPAT_BINARY_DIR}/expat.h) ADD_LIBRARY(cmexpat ${expat_SRCS}) -INSTALL(FILES COPYING DESTINATION ${CMake_DOC_DEST}/cmexpat) +INSTALL(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmexpat) diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt index ebf28ae92..8ef0e89d6 100644 --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt @@ -1,8 +1,5 @@ -# -# PROJECT(libarchive C) # -CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin) @@ -39,13 +36,24 @@ SET(LIBARCHIVE_VERSION_STRING "${VERSION}") # libarchive 2.8 == interface version 10 = 2 + 8 # libarchive 2.9 == interface version 11 = 2 + 9 # libarchive 3.0 == interface version 12 -# libarchive 3.x == interface version 12 + x -math(EXPR INTERFACE_VERSION "12 + ${_minor}") +# libarchive 3.1 == interface version 13 +math(EXPR INTERFACE_VERSION "13 + ${_minor}") # Set SOVERSION == Interface version # ?? Should there be more here ?? SET(SOVERSION "${INTERFACE_VERSION}") +# Enalbe CMAKE_PUSH_CHECK_STATE() and CMAKE_POP_CHECK_STATE() macros +# saving and restoring the state of the variables. +INCLUDE(${CMake_SOURCE_DIR}/Modules/CMakePushCheckState.cmake) + +# Initialize the state of the variables. This initialization is not +# necessary but this shows you what value the variables initially have. +SET(CMAKE_REQUIRED_DEFINITIONS) +SET(CMAKE_REQUIRED_INCLUDES) +SET(CMAKE_REQUIRED_LIBRARIES) +SET(CMAKE_REQUIRED_FLAGS) + # Disable warnings to avoid changing 3rd party code. IF("${CMAKE_C_COMPILER_ID}" MATCHES "^(GNU|Clang|XL|VisualAge|SunPro|MIPSpro|HP|Intel)$") @@ -125,7 +133,38 @@ MACRO (INSTALL_MAN __mans) INSTALL(FILES ${_man} DESTINATION "share/man/man${_mansect}") ENDFOREACH (_man) ENDMACRO (INSTALL_MAN __mans) - +# +# Find out what macro is needed to use libraries on Windows. +# +MACRO (TRY_MACRO_FOR_LIBRARY INCLUDES LIBRARIES + TRY_TYPE SAMPLE_SOURCE MACRO_LIST) + IF(WIN32 AND NOT CYGWIN) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_INCLUDES ${INCLUDES}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES}) + FOREACH(VAR ${MACRO_LIST}) + # Clear ${VAR} from CACHE If the libraries which ${VAR} was + # checked with are changed. + SET(VAR_WITH_LIB "${VAR}_WITH_LIB") + GET_PROPERTY(PREV_VAR_WITH_LIB VARIABLE PROPERTY ${VAR_WITH_LIB}) + IF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}") + UNSET(${VAR} CACHE) + ENDIF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}") + # Check if the library can be used with the macro. + IF("${TRY_TYPE}" MATCHES "COMPILES") + CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR}) + ELSEIF("${TRY_TYPE}" MATCHES "RUNS") + CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR}) + ELSE("${TRY_TYPE}" MATCHES "COMPILES") + MESSAGE(FATAL_ERROR "UNKNOWN KEYWORD \"${TRY_TYPE}\" FOR TRY_TYPE") + ENDIF("${TRY_TYPE}" MATCHES "COMPILES") + # Save the libraries which ${VAR} is checked with. + SET(${VAR_WITH_LIB} "${LIBRARIES}" CACHE INTERNAL + "Macro ${VAR} is checked with") + ENDFOREACH(VAR) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(WIN32 AND NOT CYGWIN) +ENDMACRO (TRY_MACRO_FOR_LIBRARY) # # Check compress/decompress libraries # @@ -172,13 +211,27 @@ IF(ZLIB_FOUND) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) LIST(APPEND ADDITIONAL_LIBS ${ZLIB_LIBRARIES}) IF(WIN32 AND NOT CYGWIN) - SET(CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIR}) - SET(CMAKE_REQUIRED_LIBRARIES ${ZLIB_LIBRARIES}) - CHECK_C_SOURCE_Runs( - "#ifndef ZLIB_WINAPI\n#define ZLIB_WINAPI\n#endif\n#include <zlib.h>\nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }" + # + # Test if ZLIB_WINAPI macro is needed to use. + # + TRY_MACRO_FOR_LIBRARY( + "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}" + RUNS + "#include <zlib.h>\nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }" ZLIB_WINAPI) - SET(CMAKE_REQUIRED_INCLUDES) - SET(CMAKE_REQUIRED_LIBRARIES) + IF(ZLIB_WINAPI) + ADD_DEFINITIONS(-DZLIB_WINAPI) + ELSE(ZLIB_WINAPI) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}" + COMPILES + "#include <zlib.h>\nint main() {return zlibVersion()?1:0; }" + "ZLIB_DLL;WITHOUT_ZLIB_DLL") + IF(ZLIB_DLL) + ADD_DEFINITIONS(-DZLIB_DLL) + ENDIF(ZLIB_DLL) + ENDIF(ZLIB_WINAPI) ENDIF(WIN32 AND NOT CYGWIN) ELSE(ZLIB_FOUND) MESSAGE(FATAL_ERROR "CMake requires zlib to be available to libarchive") @@ -192,11 +245,21 @@ IF(BZIP2_FOUND) SET(HAVE_BZLIB_H 1) INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR}) LIST(APPEND ADDITIONAL_LIBS ${BZIP2_LIBRARIES}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${BZIP2_INCLUDE_DIR}" "${BZIP2_LIBRARIES}" + COMPILES + "#include <bzlib.h>\nint main() {return BZ2_bzlibVersion()?1:0; }" + "USE_BZIP2_DLL;USE_BZIP2_STATIC") + IF(USE_BZIP2_DLL) + ADD_DEFINITIONS(-DUSE_BZIP2_DLL) + ELSEIF(USE_BZIP2_STATIC) + ADD_DEFINITIONS(-DUSE_BZIP2_STATIC) + ENDIF(USE_BZIP2_DLL) ENDIF(BZIP2_FOUND) MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR) -MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARY) - -IF(0) # CMake does not need LZMA support in libarchive +MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES) +IF(0) # CMake does not need LZMA or LZO2 support in libarchive # # Find LZMA # @@ -206,12 +269,45 @@ IF(LZMA_FOUND) SET(HAVE_LZMA_H 1) INCLUDE_DIRECTORIES(${LZMA_INCLUDE_DIR}) LIST(APPEND ADDITIONAL_LIBS ${LZMA_LIBRARIES}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${LZMA_INCLUDE_DIR}" "${LZMA_LIBRARIES}" + COMPILES + "#include <lzma.h>\nint main() {return (int)lzma_version_number(); }" + "WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC") + IF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC) + ADD_DEFINITIONS(-DLZMA_API_STATIC) + ENDIF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC) ELSEIF(LZMADEC_FOUND) SET(HAVE_LIBLZMADEC 1) SET(HAVE_LZMADEC_H 1) INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR}) LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES}) ENDIF(LZMA_FOUND) +# +# Find LZO2 +# +IF (LZO2_INCLUDE_DIR) + # Already in cache, be silent + SET(LZO2_FIND_QUIETLY TRUE) +ENDIF (LZO2_INCLUDE_DIR) + +FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h) +FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2) +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR) +IF(LZO2_FOUND) + SET(HAVE_LIBLZO2 1) + SET(HAVE_LZO_LZOCONF_H 1) + SET(HAVE_LZO_LZO1X_H 1) + INCLUDE_DIRECTORIES(${LZO2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LZO2_LIBRARY}) + # + # TODO: test for static library. + # +ENDIF(LZO2_FOUND) +MARK_AS_ADVANCED(CLEAR LZO2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LZO2_LIBRARY) ENDIF() # @@ -261,6 +357,7 @@ LA_CHECK_INCLUDE_FILE("process.h" HAVE_PROCESS_H) LA_CHECK_INCLUDE_FILE("pwd.h" HAVE_PWD_H) LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H) LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H) +LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H) LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H) LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H) LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H) @@ -311,14 +408,17 @@ CHECK_C_SOURCE_COMPILES( # Find Nettle # IF(ENABLE_NETTLE) - CHECK_LIBRARY_EXISTS(nettle "nettle_sha1_digest" "" NETTLE_FOUND) + FIND_PACKAGE(Nettle) IF(NETTLE_FOUND) - SET(CMAKE_REQUIRED_LIBRARIES "nettle") - FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle) - LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARY}) - ELSE(NETTLE_FOUND) - SET(ENABLE_NETTLE OFF) + SET(HAVE_LIBNETTLE 1) + SET(HAVE_NETTLE_MD5_H 1) + SET(HAVE_NETTLE_RIPEMD160_H 1) + SET(HAVE_NETTLE_SHA_H 1) + INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES}) ENDIF(NETTLE_FOUND) + MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR) + MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES) ENDIF(ENABLE_NETTLE) # @@ -332,12 +432,16 @@ ELSE() ENDIF() # FreeBSD libmd -CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND) -IF(LIBMD_FOUND) - SET(CMAKE_REQUIRED_LIBRARIES "md") - FIND_LIBRARY(LIBMD_LIBRARY NAMES md) - LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY}) -ENDIF(LIBMD_FOUND) +IF(NOT OPENSSL_FOUND) + CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND) + IF(LIBMD_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_LIBRARIES "md") + FIND_LIBRARY(LIBMD_LIBRARY NAMES md) + LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY}) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(LIBMD_FOUND) +ENDIF(NOT OPENSSL_FOUND) # # How to prove that CRYPTO functions, which have several names on various @@ -345,13 +449,8 @@ ENDIF(LIBMD_FOUND) # required libraries. # MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) - IF(HAVE_SYS_TYPES_H) - SET(CRYPTO_HEADER_CONFIG "#define HAVE_SYS_TYPES_H 1\n") - ELSE(HAVE_SYS_TYPES_H) - SET(CRYPTO_HEADER_CONFIG "") - ENDIF(HAVE_SYS_TYPES_H) - FOREACH(ALGORITHM ${ALGORITHMS}) + IF(NOT ARCHIVE_CRYPTO_${ALGORITHM}) STRING(TOLOWER "${ALGORITHM}" lower_algorithm) STRING(TOUPPER "${ALGORITHM}" algorithm) IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND) @@ -364,7 +463,7 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) # Probe the local implementation for whether this # crypto implementation is available on this platform. SET(TRY_CRYPTO_REQUIRED_INCLUDES - "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp") + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp") SET(TRY_CRYPTO_REQUIRED_LIBS) IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) SET(TRY_CRYPTO_REQUIRED_INCLUDES @@ -372,6 +471,8 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) SET(TRY_CRYPTO_REQUIRED_LIBS "-DLINK_LIBRARIES:STRING=${OPENSSL_LIBRARIES}") ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NETTLE_FOUND) + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "${TRY_CRYPTO_REQUIRED_INCLUDES};${NETTLE_INCLUDE_DIR}") SET(TRY_CRYPTO_REQUIRED_LIBS "-DLINK_LIBRARIES:STRING=${NETTLE_LIBRARY}") ELSEIF("${IMPLEMENTATION}" MATCHES "^LIBMD$" AND LIBMD_FOUND) @@ -379,10 +480,15 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) "-DLINK_LIBRARIES:STRING=${LIBMD_LIBRARY}") ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h) + FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h" + CONFDEFS_H) FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/libarchive/archive_crypto.c" ARCHIVE_CRYPTO_C) - SET(SOURCE " + SET(SOURCE "${CONFDEFS_H} + #define ARCHIVE_${algorithm}_COMPILE_TEST #define ARCHIVE_CRYPTO_${algorithm}_${IMPLEMENTATION} #define PLATFORM_CONFIG_H \"check_crypto_md.h\" @@ -392,10 +498,10 @@ ${ARCHIVE_CRYPTO_C} int main(int argc, char **argv) { - archive_${lower_crypto}_ctx ctx; - archive_${lower_crypto}_init(&ctx); - archive_${lower_crypto}_update(&ctx, *argv, argc); - archive_${lower_crypto}_final(&ctx, NULL); + archive_${lower_algorithm}_ctx ctx; + archive_${lower_algorithm}_init(&ctx); + archive_${lower_algorithm}_update(&ctx, *argv, argc); + archive_${lower_algorithm}_final(&ctx, NULL); return 0; } ") @@ -404,10 +510,16 @@ main(int argc, char **argv) FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}") MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}") + IF(CMAKE_REQUIRED_LINKER_FLAGS) + SET(CHECK_CRYPTO_ADD_LINKER_FLAGS + "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}") + ELSE(CMAKE_REQUIRED_LINKER_FLAGS) + SET(CHECK_CRYPTO_ADD_LINKER_FLAGS) + ENDIF(CMAKE_REQUIRED_LINKER_FLAGS) TRY_COMPILE(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c - CMAKE_FLAGS + CMAKE_FLAGS ${CHECK_CRYPTO_ADD_LINKER_FLAGS} "${TRY_CRYPTO_REQUIRED_LIBS}" "${TRY_CRYPTO_REQUIRED_INCLUDES}" OUTPUT_VARIABLE OUTPUT) @@ -415,6 +527,7 @@ main(int argc, char **argv) # Inform user whether or not we found it; if not, log why we didn't. IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- found") + SET(ARCHIVE_CRYPTO_${ALGORITHM} 1) ELSE (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- not found") FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log @@ -433,6 +546,7 @@ main(int argc, char **argv) LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS) ENDIF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + ENDIF(NOT ARCHIVE_CRYPTO_${ALGORITHM}) ENDFOREACH(ALGORITHM ${ALGORITHMS}) ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) @@ -448,6 +562,7 @@ ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) IF(WIN32 AND NOT CYGWIN) FOREACH(CRYPTO ${CRYPTO_LIST}) + IF(NOT ARCHIVE_CRYPTO_${CRYPTO}) IF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN) STRING(TOUPPER "${CRYPTO}" crypto) SET(ALGID "") @@ -467,9 +582,14 @@ MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) SET(ALGID "CALG_SHA_512") ENDIF ("${CRYPTO}" MATCHES "^SHA512$") - SET(SOURCE "#define ${crypto}_COMPILE_TEST -#define _WIN32_WINNT ${_WIN32_WINNT} -#define WINVER ${WINVER} + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h) + FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h" + CONFDEFS_H) + + SET(SOURCE "${CONFDEFS_H} + +#define ${crypto}_COMPILE_TEST #include <windows.h> #include <wincrypt.h> @@ -484,15 +604,22 @@ main(int argc, char **argv) FILE(WRITE "${SOURCE_FILE}" "${SOURCE}") MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN") + IF(CMAKE_REQUIRED_LINKER_FLAGS) + SET(CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS + "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}") + ELSE(CMAKE_REQUIRED_LINKER_FLAGS) + SET(CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS) + ENDIF(CMAKE_REQUIRED_LINKER_FLAGS) TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN ${CMAKE_BINARY_DIR} ${SOURCE_FILE} - CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_CURRENT_SOURCE_DIR}/libarchive" + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive" ${CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS} OUTPUT_VARIABLE OUTPUT) IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- found") + SET(ARCHIVE_CRYPTO_${CRYPTO} 1) ELSE (ARCHIVE_CRYPTO_${CRYPTO}_WIN) MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- not found") @@ -504,6 +631,7 @@ main(int argc, char **argv) ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN) + ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO}) ENDFOREACH(CRYPTO) ENDIF(WIN32 AND NOT CYGWIN) ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) @@ -517,6 +645,20 @@ ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) # MACRO(CHECK_ICONV LIB TRY_ICONV_CONST) IF(NOT HAVE_ICONV) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$") + # + # During checking iconv proto type, we should use -Werror to avoid the + # success of iconv detection with a warnig which success is a miss + # detection. So this needs for all build mode(even it's a release mode). + # + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror") + ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$") + IF (MSVC) + # NOTE: /WX option is the same as gcc's -Werror option. + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX") + ENDIF (MSVC) + # CHECK_C_SOURCE_COMPILES( "#include <stdlib.h> #include <iconv.h> @@ -532,10 +674,12 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST) SET(HAVE_ICONV true) SET(ICONV_CONST ${TRY_ICONV_CONST}) ENDIF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST}) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables ENDIF(NOT HAVE_ICONV) ENDMACRO(CHECK_ICONV TRY_ICONV_CONST) IF(ENABLE_ICONV) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables FIND_PATH(ICONV_INCLUDE_DIR iconv.h) MARK_AS_ADVANCED(ICONV_INCLUDE_DIR) IF(ICONV_INCLUDE_DIR) @@ -547,9 +691,30 @@ IF(ENABLE_ICONV) CHECK_ICONV("libc" "") # If iconv isn't in libc and we have a libiconv, try that. - FIND_LIBRARY(LIBICONV_PATH iconv) + FIND_LIBRARY(LIBICONV_PATH NAMES iconv libiconv) IF(NOT HAVE_ICONV AND LIBICONV_PATH) LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR}" "${LIBICONV_PATH}" + COMPILES + "#include <iconv.h>\nint main() {return iconv_close((iconv_t)0);}" + "WITHOUT_LIBICONV_STATIC;LIBICONV_STATIC") + IF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC) + ADD_DEFINITIONS(-DLIBICONV_STATIC) + ENDIF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC) + # + # Set up CMAKE_REQUIRED_* for CHECK_ICONV + # + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH}) + IF(LIBICONV_STATIC) + # LIBICONV_STATIC is necessary for the success of CHECK_ICONV + # on Windows. + SET(CMAKE_REQUIRED_DEFINITIONS "-DLIBICONV_STATIC") + ELSE(LIBICONV_STATIC) + SET(CMAKE_REQUIRED_DEFINITIONS) + ENDIF(LIBICONV_STATIC) CHECK_ICONV("libiconv" "const") CHECK_ICONV("libiconv" "") IF (HAVE_ICONV) @@ -561,19 +726,36 @@ IF(ENABLE_ICONV) # Find locale_charset() for libiconv. # IF(LIBICONV_PATH) + SET(CMAKE_REQUIRED_DEFINITIONS) + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES) CHECK_INCLUDE_FILES("localcharset.h" HAVE_LOCALCHARSET_H) - CHECK_FUNCTION_EXISTS_GLIBC(locale_charset HAVE_LOCALE_CHARSET) - IF(NOT HAVE_LOCALE_CHARSET) - FIND_LIBRARY(LIBCHARSET_PATH charset) - IF(LIBCHARSET_PATH) - SET(CMAKE_REQUIRED_LIBRARIES ${LIBCHARSET_PATH}) + FIND_LIBRARY(LIBCHARSET_PATH NAMES charset libcharset) + IF(LIBCHARSET_PATH) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBCHARSET_PATH}) + IF(WIN32 AND NOT CYGWIN) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR}" "${LIBCHARSET_PATH}" + COMPILES + "#include <localcharset.h>\nint main() {return locale_charset()?1:0;}" + "WITHOUT_LIBCHARSET_STATIC;LIBCHARSET_STATIC") + IF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC) + ADD_DEFINITIONS(-DLIBCHARSET_STATIC) + ENDIF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC) + IF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC) + SET(HAVE_LOCALE_CHARSET ON CACHE INTERNAL + "Have function locale_charset") + ENDIF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC) + ELSE(WIN32 AND NOT CYGWIN) CHECK_FUNCTION_EXISTS_GLIBC(locale_charset HAVE_LOCALE_CHARSET) - IF(HAVE_LOCALE_CHARSET) - LIST(APPEND ADDITIONAL_LIBS ${LIBCHARSET_PATH}) - ENDIF(HAVE_LOCALE_CHARSET) - ENDIF(LIBCHARSET_PATH) - ENDIF(NOT HAVE_LOCALE_CHARSET) + ENDIF(WIN32 AND NOT CYGWIN) + IF(HAVE_LOCALE_CHARSET) + LIST(APPEND ADDITIONAL_LIBS ${LIBCHARSET_PATH}) + ENDIF(HAVE_LOCALE_CHARSET) + ENDIF(LIBCHARSET_PATH) ENDIF(LIBICONV_PATH) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables ELSE(ENABLE_ICONV) # Make sure ICONV variables are not in CACHE after ENABLE_ICONV disabled # (once enabled). @@ -585,6 +767,10 @@ ELSE(ENABLE_ICONV) UNSET(HAVE_ICONV_libiconv_const CACHE) UNSET(ICONV_INCLUDE_DIR CACHE) UNSET(LIBICONV_PATH CACHE) + UNSET(LIBICONV_DLL CACHE) + UNSET(LIBICONV_STATIC CACHE) + UNSET(LIBCHARSET_DLL CACHE) + UNSET(LIBCHARSET_STATIC CACHE) ENDIF(ENABLE_ICONV) IF(0) # CMake does not need XML support in libarchive @@ -593,6 +779,7 @@ IF(0) # CMake does not need XML support in libarchive # FIND_PACKAGE(LibXml2) IF(LIBXML2_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) LIST(APPEND ADDITIONAL_LIBS ${LIBXML2_LIBRARIES}) SET(HAVE_LIBXML2 1) @@ -600,31 +787,45 @@ IF(LIBXML2_FOUND) SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) CHECK_INCLUDE_FILES("libxml/xmlreader.h" HAVE_LIBXML_XMLREADER_H) CHECK_INCLUDE_FILES("libxml/xmlwriter.h" HAVE_LIBXML_XMLWRITER_H) - SET(CMAKE_REQUIRED_INCLUDES "") + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR};${LIBXML2_INCLUDE_DIR}" + "ws2_32.lib;${ZLIB_LIBRARIES};${LIBICONV_PATH};${LIBXML2_LIBRARIES}" + COMPILES + "#include <stddef.h>\n#include <libxml/xmlreader.h>\nint main() {return xmlTextReaderRead((xmlTextReaderPtr)(void *)0);}" + "WITHOUT_LIBXML_STATIC;LIBXML_STATIC") + IF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC) + ADD_DEFINITIONS(-DLIBXML_STATIC) + ENDIF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables ELSE(LIBXML2_FOUND) # # Find Expat # FIND_PACKAGE(EXPAT) IF(EXPAT_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIR}) LIST(APPEND ADDITIONAL_LIBS ${EXPAT_LIBRARIES}) SET(HAVE_LIBEXPAT 1) LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables ENDIF(EXPAT_FOUND) ENDIF(LIBXML2_FOUND) +MARK_AS_ADVANCED(CLEAR LIBXML2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LIBXML2_LIBRARIES) ENDIF() # # Check functions # +CMAKE_PUSH_CHECK_STATE() # Save the state of the variables IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$") # # During checking functions, we should use -fno-builtin to avoid the # failure of function detection which failure is an error "conflicting # types for built-in function" caused by using -Werror option. # - SET(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-builtin") ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$") CHECK_SYMBOL_EXISTS(_CrtSetReportMode "crtdbg.h" HAVE__CrtSetReportMode) @@ -632,6 +833,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS) CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN) CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT) CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R) +CHECK_FUNCTION_EXISTS_GLIBC(dirfd HAVE_DIRFD) CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR) CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS) CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD) @@ -663,7 +865,6 @@ CHECK_FUNCTION_EXISTS_GLIBC(localtime_r HAVE_LOCALTIME_R) CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT) CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES) CHECK_FUNCTION_EXISTS_GLIBC(mbrtowc HAVE_MBRTOWC) -CHECK_FUNCTION_EXISTS_GLIBC(mbsnrtowcs HAVE_MBSNRTOWCS) CHECK_FUNCTION_EXISTS_GLIBC(memmove HAVE_MEMMOVE) CHECK_FUNCTION_EXISTS_GLIBC(mkdir HAVE_MKDIR) CHECK_FUNCTION_EXISTS_GLIBC(mkfifo HAVE_MKFIFO) @@ -673,6 +874,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO) CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT) CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE) CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL) +CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP) CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK) CHECK_FUNCTION_EXISTS_GLIBC(select HAVE_SELECT) CHECK_FUNCTION_EXISTS_GLIBC(setenv HAVE_SETENV) @@ -697,7 +899,6 @@ CHECK_FUNCTION_EXISTS_GLIBC(wcrtomb HAVE_WCRTOMB) CHECK_FUNCTION_EXISTS_GLIBC(wcscmp HAVE_WCSCMP) CHECK_FUNCTION_EXISTS_GLIBC(wcscpy HAVE_WCSCPY) CHECK_FUNCTION_EXISTS_GLIBC(wcslen HAVE_WCSLEN) -CHECK_FUNCTION_EXISTS_GLIBC(wcsnrtombs HAVE_WCSNRTOMBS) CHECK_FUNCTION_EXISTS_GLIBC(wctomb HAVE_WCTOMB) CHECK_FUNCTION_EXISTS_GLIBC(_ctime64_s HAVE__CTIME64_S) CHECK_FUNCTION_EXISTS_GLIBC(_fseeki64 HAVE__FSEEKI64) @@ -714,10 +915,7 @@ CHECK_FUNCTION_EXISTS(vprintf HAVE_VPRINTF) CHECK_FUNCTION_EXISTS(wmemcmp HAVE_WMEMCMP) CHECK_FUNCTION_EXISTS(wmemcpy HAVE_WMEMCPY) -# Restore CMAKE_REQUIRED_FLAGS -IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$") - SET(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS}) -ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$") +CMAKE_POP_CHECK_STATE() # Restore the state of the variables # Make sure we have the POSIX version of readdir_r, not the # older 2-argument version. @@ -1036,6 +1234,8 @@ IF(ENABLE_ACL) CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP) CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK) CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP) + CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP) + CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP) # MacOS has an acl.h that isn't POSIX. It can be detected by # checking for ACL_USER @@ -1111,4 +1311,4 @@ ENDIF(APPLE) add_subdirectory(libarchive) -install(FILES COPYING DESTINATION ${CMake_DOC_DEST}/cmlibarchive) +install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmlibarchive) diff --git a/Utilities/cmlibarchive/README-CMake.txt b/Utilities/cmlibarchive/README-CMake.txt index 45cb0939e..ab105f064 100644 --- a/Utilities/cmlibarchive/README-CMake.txt +++ b/Utilities/cmlibarchive/README-CMake.txt @@ -11,7 +11,7 @@ branch, but it is merged into our history. Update libarchive from upstream as follows. Create a local branch to explicitly reference the upstream snapshot branch head: - git branch libarchive-upstream 4f4fe6e5 + git branch libarchive-upstream 35df7c8b Use a temporary directory to checkout the branch: @@ -24,7 +24,7 @@ Use a temporary directory to checkout the branch: Now place the (reduced) libarchive content in this directory. See instructions shown by - git log 4f4fe6e5 + git log 35df7c8b for help extracting the content from the upstream svn repo. Then run the following commands to commit the new version. Substitute the @@ -34,8 +34,8 @@ appropriate date and version number: GIT_AUTHOR_NAME='LibArchive Upstream' \ GIT_AUTHOR_EMAIL='libarchive-discuss@googlegroups.com' \ - GIT_AUTHOR_DATE='2011-12-31 13:54:34 -0500' \ - git commit -m 'libarchive 3.0.2-r4051 (reduced)' && + GIT_AUTHOR_DATE='2013-02-09 12:17:57 -0500' \ + git commit -m 'libarchive 3.1.2 (reduced)' && git commit --amend Edit the commit message to describe the procedure used to obtain the diff --git a/Utilities/cmlibarchive/build/cmake/FindLibGCC.cmake b/Utilities/cmlibarchive/build/cmake/FindLibGCC.cmake new file mode 100644 index 000000000..7985f2b00 --- /dev/null +++ b/Utilities/cmlibarchive/build/cmake/FindLibGCC.cmake @@ -0,0 +1,22 @@ +# - Find libgcc +# Find the libgcc library. +# +# LIBGCC_LIBRARIES - List of libraries when using libgcc +# LIBGCC_FOUND - True if libgcc found. + +IF (LIBGCC_LIBRARY) + # Already in cache, be silent + SET(LIBGCC_FIND_QUIETLY TRUE) +ENDIF (LIBGCC_LIBRARY) + +FIND_LIBRARY(LIBGCC_LIBRARY NAMES gcc libgcc) + +# handle the QUIETLY and REQUIRED arguments and set LIBGCC_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGCC DEFAULT_MSG LIBGCC_LIBRARY) + +IF(LIBGCC_FOUND) + SET(LIBGCC_LIBRARIES ${LIBGCC_LIBRARY}) + SET(HAVE_LIBGCC 1) +ENDIF(LIBGCC_FOUND) diff --git a/Utilities/cmlibarchive/build/cmake/FindNettle.cmake b/Utilities/cmlibarchive/build/cmake/FindNettle.cmake new file mode 100644 index 000000000..1f66610f0 --- /dev/null +++ b/Utilities/cmlibarchive/build/cmake/FindNettle.cmake @@ -0,0 +1,23 @@ +# - Find Nettle +# Find the Nettle include directory and library +# +# NETTLE_INCLUDE_DIR - where to find <nettle/sha.h>, etc. +# NETTLE_LIBRARIES - List of libraries when using libnettle. +# NETTLE_FOUND - True if libnettle found. + +IF (NETTLE_INCLUDE_DIR) + # Already in cache, be silent + SET(NETTLE_FIND_QUIETLY TRUE) +ENDIF (NETTLE_INCLUDE_DIR) + +FIND_PATH(NETTLE_INCLUDE_DIR nettle/md5.h nettle/ripemd160.h nettle/sha.h) +FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle) + +# handle the QUIETLY and REQUIRED arguments and set NETTLE_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETTLE DEFAULT_MSG NETTLE_LIBRARY NETTLE_INCLUDE_DIR) + +IF(NETTLE_FOUND) + SET(NETTLE_LIBRARIES ${NETTLE_LIBRARY}) +ENDIF(NETTLE_FOUND) diff --git a/Utilities/cmlibarchive/build/cmake/FindPCREPOSIX.cmake b/Utilities/cmlibarchive/build/cmake/FindPCREPOSIX.cmake new file mode 100644 index 000000000..7cc40ec0f --- /dev/null +++ b/Utilities/cmlibarchive/build/cmake/FindPCREPOSIX.cmake @@ -0,0 +1,34 @@ +# - Find pcreposix +# Find the native PCRE and PCREPOSIX include and libraries +# +# PCRE_INCLUDE_DIR - where to find pcreposix.h, etc. +# PCREPOSIX_LIBRARIES - List of libraries when using libpcreposix. +# PCRE_LIBRARIES - List of libraries when using libpcre. +# PCREPOSIX_FOUND - True if libpcreposix found. +# PCRE_FOUND - True if libpcre found. + +IF (PCRE_INCLUDE_DIR) + # Already in cache, be silent + SET(PCRE_FIND_QUIETLY TRUE) +ENDIF (PCRE_INCLUDE_DIR) + +FIND_PATH(PCRE_INCLUDE_DIR pcreposix.h) +FIND_LIBRARY(PCREPOSIX_LIBRARY NAMES pcreposix libpcreposix) +FIND_LIBRARY(PCRE_LIBRARY NAMES pcre libpcre) + +# handle the QUIETLY and REQUIRED arguments and set PCREPOSIX_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCREPOSIX DEFAULT_MSG PCREPOSIX_LIBRARY PCRE_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY) + +IF(PCREPOSIX_FOUND) + SET(PCREPOSIX_LIBRARIES ${PCREPOSIX_LIBRARY}) + SET(HAVE_LIBPCREPOSIX 1) + SET(HAVE_PCREPOSIX_H 1) +ENDIF(PCREPOSIX_FOUND) + +IF(PCRE_FOUND) + SET(PCRE_LIBRARIES ${PCRE_LIBRARY}) + SET(HAVE_LIBPCRE 1) +ENDIF(PCRE_FOUND) diff --git a/Utilities/cmlibarchive/build/cmake/config.h.in b/Utilities/cmlibarchive/build/cmake/config.h.in index ff97cbd98..750ae660a 100644 --- a/Utilities/cmlibarchive/build/cmake/config.h.in +++ b/Utilities/cmlibarchive/build/cmake/config.h.in @@ -393,6 +393,9 @@ typedef uint64_t uintmax_t; */ #cmakedefine HAVE_DIRENT_H 1 +/* Define to 1 if you have the `dirfd' function. */ +#cmakedefine HAVE_DIRFD 1 + /* Define to 1 if you have the <dlfcn.h> header file. */ #cmakedefine HAVE_DLFCN_H 1 @@ -579,12 +582,27 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `expat' library (-lexpat). */ #cmakedefine HAVE_LIBEXPAT 1 +/* Define to 1 if you have the `gcc' library (-lgcc). */ +#cmakedefine HAVE_LIBGCC 1 + /* Define to 1 if you have the `lzma' library (-llzma). */ #cmakedefine HAVE_LIBLZMA 1 /* Define to 1 if you have the `lzmadec' library (-llzmadec). */ #cmakedefine HAVE_LIBLZMADEC 1 +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +#cmakedefine HAVE_LIBLZO2 1 + +/* Define to 1 if you have the `nettle' library (-lnettle). */ +#cmakedefine HAVE_LIBNETTLE 1 + +/* Define to 1 if you have the `pcre' library (-lpcre). */ +#cmakedefine HAVE_LIBPCRE 1 + +/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */ +#cmakedefine HAVE_LIBPCREPOSIX 1 + /* Define to 1 if you have the `xml2' library (-lxml2). */ #cmakedefine HAVE_LIBXML2 1 @@ -615,6 +633,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the <linux/magic.h> header file. */ #cmakedefine HAVE_LINUX_MAGIC_H 1 +/* Define to 1 if you have the <linux/types.h> header file. */ +#cmakedefine HAVE_LINUX_TYPES_H 1 + /* Define to 1 if you have the `listea' function. */ #cmakedefine HAVE_LISTEA 1 @@ -664,12 +685,15 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the <lzma.h> header file. */ #cmakedefine HAVE_LZMA_H 1 +/* Define to 1 if you have the <lzo/lzo1x.h> header file. */ +#cmakedefine HAVE_LZO_LZO1X_H 1 + +/* Define to 1 if you have the <lzo/lzoconf.h> header file. */ +#cmakedefine HAVE_LZO_LZOCONF_H 1 + /* Define to 1 if you have the `mbrtowc' function. */ #cmakedefine HAVE_MBRTOWC 1 -/* Define to 1 if you have the `mbsnrtowcs' function. */ -#cmakedefine HAVE_MBSNRTOWCS 1 - /* Define to 1 if you have the `memmove' function. */ #cmakedefine HAVE_MEMMOVE 1 @@ -691,6 +715,15 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ #cmakedefine HAVE_NDIR_H 1 +/* Define to 1 if you have the <nettle/md5.h> header file. */ +#cmakedefine HAVE_NETTLE_MD5_H 1 + +/* Define to 1 if you have the <nettle/ripemd160.h> header file. */ +#cmakedefine HAVE_NETTLE_RIPEMD160_H 1 + +/* Define to 1 if you have the <nettle/sha.h> header file. */ +#cmakedefine HAVE_NETTLE_SHA_H 1 + /* Define to 1 if you have the `nl_langinfo' function. */ #cmakedefine HAVE_NL_LANGINFO 1 @@ -700,6 +733,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the <paths.h> header file. */ #cmakedefine HAVE_PATHS_H 1 +/* Define to 1 if you have the <pcreposix.h> header file. */ +#cmakedefine HAVE_PCREPOSIX_H 1 + /* Define to 1 if you have the `pipe' function. */ #cmakedefine HAVE_PIPE 1 @@ -709,6 +745,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the <poll.h> header file. */ #cmakedefine HAVE_POLL_H 1 +/* Define to 1 if you have the `posix_spawnp' function. */ +#cmakedefine HAVE_POSIX_SPAWNP 1 + /* Define to 1 if you have the <process.h> header file. */ #cmakedefine HAVE_PROCESS_H 1 @@ -742,6 +781,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the <signal.h> header file. */ #cmakedefine HAVE_SIGNAL_H 1 +/* Define to 1 if you have the <spawn.h> header file. */ +#cmakedefine HAVE_SPAWN_H 1 + /* Define to 1 if you have the `statfs' function. */ #cmakedefine HAVE_STATFS 1 @@ -952,9 +994,6 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `wcslen' function. */ #cmakedefine HAVE_WCSLEN 1 -/* Define to 1 if you have the `wcsnrtombs' function. */ -#cmakedefine HAVE_WCSNRTOMBS 1 - /* Define to 1 if you have the `wctomb' function. */ #cmakedefine HAVE_WCTOMB 1 diff --git a/Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh b/Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh index 95dbe167d..925de5c85 100644..100755 --- a/Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh +++ b/Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh @@ -1,10 +1,13 @@ #!/bin/sh # -# This needs http://unicode.org/Public/UNIDATA/UnicodeData.txt +# This needs http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt # inputfile="$1" # Expect UnicodeData.txt outfile=archive_string_composition.h pickout=/tmp/mk_unicode_composition_tbl$$.awk +pickout2=/tmp/mk_unicode_composition_tbl2$$.awk +#nfdtmp=/tmp/mk_unicode_decomposition_tmp$$.txt +nfdtmp="nfdtmpx" ################################################################################# # # Append the file header of "archive_string_composition.h" @@ -14,7 +17,7 @@ append_copyright() { cat > ${outfile} <<CR_END /*- - * Copyright (c) 2011 libarchive Project + * Copyright (c) 2011-2012 libarchive Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +47,7 @@ cat > ${outfile} <<CR_END /* * ATTENTION! * This file is generated by build/utils/gen_archive_string_composition_h.sh - * from http://unicode.org/Public/UNIDATA/UnicodeData.txt + * from http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt * * See also http://unicode.org/report/tr15/ */ @@ -76,6 +79,7 @@ BEGIN { min = ""; max = ""; cmd="sort | awk -F ' ' '{printf \"\\\\t{ 0x%s , 0x%s , 0x%s },\\\\n\",\$1,\$2,\$3}'" + nfdtbl="${nfdtmp}" print "static const struct unicode_composition_table u_composition_table[] = {" } END { @@ -178,7 +182,6 @@ END { } print "};" print "" - print "#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */" } # # @@ -241,7 +244,7 @@ function hextoi(hex) #} # # Exclusion code points specified by -# http://unicode.org/Public/UNIDATA/CompositionExclusions.txt +# http://unicode.org/Public/6.0.0/ucd/CompositionExclusions.txt ## # 1. Script Specifices ## @@ -404,6 +407,35 @@ function hextoi(hex) print "0"cp[1], "0"cp[2], "0"\$1 | cmd else print cp[1], cp[2], \$1 | cmd + # NFC ==> NFD table. + if (length(\$1) == 4) + print "0"\$1, "0"cp[1], "0"cp[2] >>nfdtbl + else + print \$1, cp[1], cp[2] >>nfdtbl +} +AWK_END +################################################################################# +# awk script +# +################################################################################# +cat > ${pickout2} <<AWK_END +# +BEGIN { + FS = " " + print "struct unicode_decomposition_table {" + print "\tuint32_t nfc;" + print "\tuint32_t cp1;" + print "\tuint32_t cp2;" + print "};" + print "" + print "static const struct unicode_decomposition_table u_decomposition_table[] = {" +} +END { + print "};" + print "" +} +{ +printf "\t{ 0x%s , 0x%s , 0x%s },\n", \$1, \$2, \$3; } AWK_END ################################################################################# @@ -413,6 +445,11 @@ AWK_END ################################################################################# append_copyright awk -f ${pickout} ${inputfile} >> ${outfile} +awk -f ${pickout2} ${nfdtmp} >> ${outfile} +echo "#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */" >> ${outfile} +echo "" >> ${outfile} # # Remove awk the script. rm ${pickout} +rm ${pickout2} +rm ${nfdtmp} diff --git a/Utilities/cmlibarchive/build/version b/Utilities/cmlibarchive/build/version index ee575c8f5..937b126a2 100644 --- a/Utilities/cmlibarchive/build/version +++ b/Utilities/cmlibarchive/build/version @@ -1 +1 @@ -3000002 +3001002 diff --git a/Utilities/cmlibarchive/libarchive/CMakeLists.txt b/Utilities/cmlibarchive/libarchive/CMakeLists.txt index 738419597..42781bc3c 100644 --- a/Utilities/cmlibarchive/libarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/libarchive/CMakeLists.txt @@ -15,6 +15,9 @@ SET(include_HEADERS SET(libarchive_SOURCES archive_acl.c archive_check_magic.c + archive_cmdline.c + archive_cmdline_private.h + archive_crc32.h archive_crypto.c archive_crypto_private.h archive_endian.h @@ -28,8 +31,12 @@ SET(libarchive_SOURCES archive_entry_stat.c archive_entry_strmode.c archive_entry_xattr.c + archive_getdate.c + archive_match.c archive_options.c archive_options_private.h + archive_pathmatch.c + archive_pathmatch.h archive_platform.h archive_ppmd_private.h archive_ppmd7.c @@ -38,6 +45,7 @@ SET(libarchive_SOURCES archive_rb.c archive_rb.h archive_read.c + archive_read_append_filter.c archive_read_data_into_fd.c archive_read_disk_entry_from_file.c archive_read_disk_posix.c @@ -49,11 +57,15 @@ SET(libarchive_SOURCES archive_read_open_filename.c archive_read_open_memory.c archive_read_private.h + archive_read_set_format.c archive_read_set_options.c archive_read_support_filter_all.c archive_read_support_filter_bzip2.c archive_read_support_filter_compress.c archive_read_support_filter_gzip.c + archive_read_support_filter_grzip.c + archive_read_support_filter_lrzip.c + archive_read_support_filter_lzop.c archive_read_support_filter_none.c archive_read_support_filter_program.c archive_read_support_filter_rpm.c @@ -81,6 +93,7 @@ SET(libarchive_SOURCES archive_util.c archive_virtual.c archive_write.c + archive_write_disk_acl.c archive_write_disk_posix.c archive_write_disk_private.h archive_write_disk_set_standard_lookup.c @@ -89,11 +102,18 @@ SET(libarchive_SOURCES archive_write_open_file.c archive_write_open_filename.c archive_write_open_memory.c + archive_write_add_filter.c + archive_write_add_filter_b64encode.c + archive_write_add_filter_by_name.c archive_write_add_filter_bzip2.c archive_write_add_filter_compress.c + archive_write_add_filter_grzip.c archive_write_add_filter_gzip.c + archive_write_add_filter_lrzip.c + archive_write_add_filter_lzop.c archive_write_add_filter_none.c archive_write_add_filter_program.c + archive_write_add_filter_uuencode.c archive_write_add_filter_xz.c archive_write_set_format.c archive_write_set_format_7zip.c @@ -107,10 +127,11 @@ SET(libarchive_SOURCES archive_write_set_format_pax.c archive_write_set_format_shar.c archive_write_set_format_ustar.c + archive_write_set_format_v7tar.c archive_write_set_format_xar.c archive_write_set_format_zip.c archive_write_set_options.c - filter_fork.c + filter_fork_posix.c filter_fork.h ) diff --git a/Utilities/cmlibarchive/libarchive/archive.h b/Utilities/cmlibarchive/libarchive/archive.h index 9b6b1b0c2..1a1d32a6d 100644 --- a/Utilities/cmlibarchive/libarchive/archive.h +++ b/Utilities/cmlibarchive/libarchive/archive.h @@ -63,13 +63,6 @@ # else # define __LA_SSIZE_T long # endif -# if defined(__BORLANDC__) -# define __LA_UID_T uid_t -# define __LA_GID_T gid_t -# else -# define __LA_UID_T short -# define __LA_GID_T short -# endif #else # include <unistd.h> /* ssize_t, uid_t, and gid_t */ # if defined(_SCO_DS) || defined(__osf__) @@ -78,8 +71,6 @@ # define __LA_INT64_T int64_t # endif # define __LA_SSIZE_T ssize_t -# define __LA_UID_T uid_t -# define __LA_GID_T gid_t #endif /* @@ -113,6 +104,9 @@ #define __LA_PRINTF(fmtarg, firstvararg) /* nothing */ #endif +/* CMake uses some deprecated APIs to build with old libarchive versions. */ +#define __LA_DEPRECATED + #ifdef __cplusplus extern "C" { #endif @@ -134,13 +128,13 @@ extern "C" { * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3000002 +#define ARCHIVE_VERSION_NUMBER 3001002 __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_STRING "libarchive 3.0.2" +#define ARCHIVE_VERSION_STRING "libarchive 3.1.2" __LA_DECL const char * archive_version_string(void); /* Declare our basic types. */ @@ -210,6 +204,13 @@ typedef int archive_open_callback(struct archive *, void *_client_data); typedef int archive_close_callback(struct archive *, void *_client_data); +/* Switches from one client data object to the next/prev client data object. + * This is useful for reading from different data blocks such as a set of files + * that make up one large file. + */ +typedef int archive_switch_callback(struct archive *, void *_client_data1, + void *_client_data2); + /* * Codes to identify various stream filters. */ @@ -223,6 +224,9 @@ typedef int archive_close_callback(struct archive *, void *_client_data); #define ARCHIVE_FILTER_UU 7 #define ARCHIVE_FILTER_RPM 8 #define ARCHIVE_FILTER_LZIP 9 +#define ARCHIVE_FILTER_LRZIP 10 +#define ARCHIVE_FILTER_LZOP 11 +#define ARCHIVE_FILTER_GRZIP 12 #if ARCHIVE_VERSION_NUMBER < 4000000 #define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE @@ -235,6 +239,7 @@ typedef int archive_close_callback(struct archive *, void *_client_data); #define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU #define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM #define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP +#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP #endif /* @@ -307,37 +312,49 @@ __LA_DECL struct archive *archive_read_new(void); */ #if ARCHIVE_VERSION_NUMBER < 4000000 -__LA_DECL int archive_read_support_compression_all(struct archive *); -__LA_DECL int archive_read_support_compression_bzip2(struct archive *); -__LA_DECL int archive_read_support_compression_compress(struct archive *); -__LA_DECL int archive_read_support_compression_gzip(struct archive *); -__LA_DECL int archive_read_support_compression_lzip(struct archive *); -__LA_DECL int archive_read_support_compression_lzma(struct archive *); -__LA_DECL int archive_read_support_compression_none(struct archive *); +__LA_DECL int archive_read_support_compression_all(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_bzip2(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_compress(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_gzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_lzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_lzma(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_none(struct archive *) + __LA_DEPRECATED; __LA_DECL int archive_read_support_compression_program(struct archive *, - const char *command); + const char *command) __LA_DEPRECATED; __LA_DECL int archive_read_support_compression_program_signature (struct archive *, const char *, - const void * /* match */, size_t); - -__LA_DECL int archive_read_support_compression_rpm(struct archive *); -__LA_DECL int archive_read_support_compression_uu(struct archive *); -__LA_DECL int archive_read_support_compression_xz(struct archive *); + const void * /* match */, size_t) __LA_DEPRECATED; + +__LA_DECL int archive_read_support_compression_rpm(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_uu(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_xz(struct archive *) + __LA_DEPRECATED; #endif __LA_DECL int archive_read_support_filter_all(struct archive *); __LA_DECL int archive_read_support_filter_bzip2(struct archive *); __LA_DECL int archive_read_support_filter_compress(struct archive *); __LA_DECL int archive_read_support_filter_gzip(struct archive *); +__LA_DECL int archive_read_support_filter_grzip(struct archive *); +__LA_DECL int archive_read_support_filter_lrzip(struct archive *); __LA_DECL int archive_read_support_filter_lzip(struct archive *); __LA_DECL int archive_read_support_filter_lzma(struct archive *); +__LA_DECL int archive_read_support_filter_lzop(struct archive *); __LA_DECL int archive_read_support_filter_none(struct archive *); __LA_DECL int archive_read_support_filter_program(struct archive *, const char *command); __LA_DECL int archive_read_support_filter_program_signature - (struct archive *, const char *, + (struct archive *, const char * /* cmd */, const void * /* match */, size_t); - __LA_DECL int archive_read_support_filter_rpm(struct archive *); __LA_DECL int archive_read_support_filter_uu(struct archive *); __LA_DECL int archive_read_support_filter_xz(struct archive *); @@ -359,6 +376,17 @@ __LA_DECL int archive_read_support_format_tar(struct archive *); __LA_DECL int archive_read_support_format_xar(struct archive *); __LA_DECL int archive_read_support_format_zip(struct archive *); +/* Functions to manually set the format and filters to be used. This is + * useful to bypass the bidding process when the format and filters to use + * is known in advance. + */ +__LA_DECL int archive_read_set_format(struct archive *, int); +__LA_DECL int archive_read_append_filter(struct archive *, int); +__LA_DECL int archive_read_append_filter_program(struct archive *, + const char *); +__LA_DECL int archive_read_append_filter_program_signature + (struct archive *, const char *, const void * /* match */, size_t); + /* Set various callbacks. */ __LA_DECL int archive_read_set_open_callback(struct archive *, archive_open_callback *); @@ -370,8 +398,23 @@ __LA_DECL int archive_read_set_skip_callback(struct archive *, archive_skip_callback *); __LA_DECL int archive_read_set_close_callback(struct archive *, archive_close_callback *); -/* The callback data is provided to all of the callbacks above. */ +/* Callback used to switch between one data object to the next */ +__LA_DECL int archive_read_set_switch_callback(struct archive *, + archive_switch_callback *); + +/* This sets the first data object. */ __LA_DECL int archive_read_set_callback_data(struct archive *, void *); +/* This sets data object at specified index */ +__LA_DECL int archive_read_set_callback_data2(struct archive *, void *, + unsigned int); +/* This adds a data object at the specified index. */ +__LA_DECL int archive_read_add_callback_data(struct archive *, void *, + unsigned int); +/* This appends a data object to the end of list */ +__LA_DECL int archive_read_append_callback_data(struct archive *, void *); +/* This prepends a data object to the beginning of list */ +__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *); + /* Opening freezes the callbacks. */ __LA_DECL int archive_read_open1(struct archive *); @@ -391,11 +434,15 @@ __LA_DECL int archive_read_open2(struct archive *, void *_client_data, /* Use this if you know the filename. Note: NULL indicates stdin. */ __LA_DECL int archive_read_open_filename(struct archive *, const char *_filename, size_t _block_size); +/* Use this for reading multivolume files by filenames. + * NOTE: Must be NULL terminated. Sorting is NOT done. */ +__LA_DECL int archive_read_open_filenames(struct archive *, + const char **_filenames, size_t _block_size); __LA_DECL int archive_read_open_filename_w(struct archive *, const wchar_t *_filename, size_t _block_size); /* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */ __LA_DECL int archive_read_open_file(struct archive *, - const char *_filename, size_t _block_size); + const char *_filename, size_t _block_size) __LA_DEPRECATED; /* Read an archive that's stored in memory. */ __LA_DECL int archive_read_open_memory(struct archive *, void * buff, size_t size); @@ -427,6 +474,9 @@ __LA_DECL __LA_INT64_T archive_read_header_position(struct archive *); __LA_DECL __LA_SSIZE_T archive_read_data(struct archive *, void *, size_t); +/* Seek within the body of an entry. Similar to lseek(2). */ +__LA_DECL __LA_INT64_T archive_seek_data(struct archive *, __LA_INT64_T, int); + /* * A zero-copy version of archive_read_data that also exposes the file offset * of each returned block. Note that the client has no way to specify @@ -510,6 +560,12 @@ __LA_DECL int archive_read_set_options(struct archive *_a, /* Default: Do not restore Mac extended metadata. */ /* This has no effect except on Mac OS. */ #define ARCHIVE_EXTRACT_MAC_METADATA (0x2000) +/* Default: Use HFS+ compression if it was compressed. */ +/* This has no effect except on Mac OS v10.6 or later. */ +#define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000) +/* Default: Do not use HFS+ compression if it was not compressed. */ +/* This has no effect except on Mac OS v10.6 or later. */ +#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000) __LA_DECL int archive_read_extract(struct archive *, struct archive_entry *, int flags); @@ -530,7 +586,7 @@ __LA_DECL int archive_read_close(struct archive *); __LA_DECL int archive_read_free(struct archive *); #if ARCHIVE_VERSION_NUMBER < 4000000 /* Synonym for archive_read_free() for backwards compatibility. */ -__LA_DECL int archive_read_finish(struct archive *); +__LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED; #endif /*- @@ -563,25 +619,41 @@ __LA_DECL int archive_write_set_skip_file(struct archive *, __LA_INT64_T, __LA_INT64_T); #if ARCHIVE_VERSION_NUMBER < 4000000 -__LA_DECL int archive_write_set_compression_bzip2(struct archive *); -__LA_DECL int archive_write_set_compression_compress(struct archive *); -__LA_DECL int archive_write_set_compression_gzip(struct archive *); -__LA_DECL int archive_write_set_compression_lzip(struct archive *); -__LA_DECL int archive_write_set_compression_lzma(struct archive *); -__LA_DECL int archive_write_set_compression_none(struct archive *); +__LA_DECL int archive_write_set_compression_bzip2(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_compress(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_gzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_lzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_lzma(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_none(struct archive *) + __LA_DEPRECATED; __LA_DECL int archive_write_set_compression_program(struct archive *, - const char *cmd); -__LA_DECL int archive_write_set_compression_xz(struct archive *); + const char *cmd) __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_xz(struct archive *) + __LA_DEPRECATED; #endif +/* A convenience function to set the filter based on the code. */ +__LA_DECL int archive_write_add_filter(struct archive *, int filter_code); +__LA_DECL int archive_write_add_filter_by_name(struct archive *, + const char *name); +__LA_DECL int archive_write_add_filter_b64encode(struct archive *); __LA_DECL int archive_write_add_filter_bzip2(struct archive *); __LA_DECL int archive_write_add_filter_compress(struct archive *); +__LA_DECL int archive_write_add_filter_grzip(struct archive *); __LA_DECL int archive_write_add_filter_gzip(struct archive *); +__LA_DECL int archive_write_add_filter_lrzip(struct archive *); __LA_DECL int archive_write_add_filter_lzip(struct archive *); __LA_DECL int archive_write_add_filter_lzma(struct archive *); +__LA_DECL int archive_write_add_filter_lzop(struct archive *); __LA_DECL int archive_write_add_filter_none(struct archive *); __LA_DECL int archive_write_add_filter_program(struct archive *, const char *cmd); +__LA_DECL int archive_write_add_filter_uuencode(struct archive *); __LA_DECL int archive_write_add_filter_xz(struct archive *); @@ -598,14 +670,18 @@ __LA_DECL int archive_write_set_format_cpio_newc(struct archive *); __LA_DECL int archive_write_set_format_gnutar(struct archive *); __LA_DECL int archive_write_set_format_iso9660(struct archive *); __LA_DECL int archive_write_set_format_mtree(struct archive *); +__LA_DECL int archive_write_set_format_mtree_classic(struct archive *); /* TODO: int archive_write_set_format_old_tar(struct archive *); */ __LA_DECL int archive_write_set_format_pax(struct archive *); __LA_DECL int archive_write_set_format_pax_restricted(struct archive *); __LA_DECL int archive_write_set_format_shar(struct archive *); __LA_DECL int archive_write_set_format_shar_dump(struct archive *); __LA_DECL int archive_write_set_format_ustar(struct archive *); +__LA_DECL int archive_write_set_format_v7tar(struct archive *); __LA_DECL int archive_write_set_format_xar(struct archive *); __LA_DECL int archive_write_set_format_zip(struct archive *); +__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *); +__LA_DECL int archive_write_zip_set_compression_store(struct archive *); __LA_DECL int archive_write_open(struct archive *, void *, archive_open_callback *, archive_write_callback *, archive_close_callback *); @@ -614,7 +690,8 @@ __LA_DECL int archive_write_open_filename(struct archive *, const char *_file); __LA_DECL int archive_write_open_filename_w(struct archive *, const wchar_t *_file); /* A deprecated synonym for archive_write_open_filename() */ -__LA_DECL int archive_write_open_file(struct archive *, const char *_file); +__LA_DECL int archive_write_open_file(struct archive *, const char *_file) + __LA_DEPRECATED; __LA_DECL int archive_write_open_FILE(struct archive *, FILE *); /* _buffSize is the size of the buffer, _used refers to a variable that * will be updated after each write into the buffer. */ @@ -636,12 +713,16 @@ __LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *, __LA_DECL int archive_write_finish_entry(struct archive *); __LA_DECL int archive_write_close(struct archive *); +/* Marks the archive as FATAL so that a subsequent free() operation + * won't try to close() cleanly. Provides a fast abort capability + * when the client discovers that things have gone wrong. */ +__LA_DECL int archive_write_fail(struct archive *); /* This can fail if the archive wasn't already closed, in which case * archive_write_free() will implicitly call archive_write_close(). */ __LA_DECL int archive_write_free(struct archive *); #if ARCHIVE_VERSION_NUMBER < 4000000 /* Synonym for archive_write_free() for backwards compatibility. */ -__LA_DECL int archive_write_finish(struct archive *); +__LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED; #endif /* @@ -765,11 +846,42 @@ __LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *); * traversal. */ __LA_DECL int archive_read_disk_descend(struct archive *); +__LA_DECL int archive_read_disk_can_descend(struct archive *); __LA_DECL int archive_read_disk_current_filesystem(struct archive *); __LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *); __LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *); /* Request that the access time of the entry visited by travesal be restored. */ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *); +/* + * Set behavior. The "flags" argument selects optional behavior. + */ +/* Request that the access time of the entry visited by travesal be restored. + * This is the same as archive_read_disk_set_atime_restored. */ +#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001) +/* Default: Do not skip an entry which has nodump flags. */ +#define ARCHIVE_READDISK_HONOR_NODUMP (0x0002) +/* Default: Skip a mac resource fork file whose prefix is "._" because of + * using copyfile. */ +#define ARCHIVE_READDISK_MAC_COPYFILE (0x0004) +/* Default: Do not traverse mount points. */ +#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008) + +__LA_DECL int archive_read_disk_set_behavior(struct archive *, + int flags); + +/* + * Set archive_match object that will be used in archive_read_disk to + * know whether an entry should be skipped. The callback function + * _excluded_func will be invoked when an entry is skipped by the result + * of archive_match. + */ +__LA_DECL int archive_read_disk_set_matching(struct archive *, + struct archive *_matching, void (*_excluded_func) + (struct archive *, void *, struct archive_entry *), + void *_client_data); +__LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *, + int (*_metadata_filter_func)(struct archive *, void *, + struct archive_entry *), void *_client_data); /* * Accessor functions to read/set various information in @@ -789,13 +901,17 @@ __LA_DECL const char * archive_filter_name(struct archive *, int); /* These don't properly handle multiple filters, so are deprecated and * will eventually be removed. */ /* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */ -__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *); +__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *) + __LA_DEPRECATED; /* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */ -__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *); +__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *) + __LA_DEPRECATED; /* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */ -__LA_DECL const char *archive_compression_name(struct archive *); +__LA_DECL const char *archive_compression_name(struct archive *) + __LA_DEPRECATED; /* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */ -__LA_DECL int archive_compression(struct archive *); +__LA_DECL int archive_compression(struct archive *) + __LA_DEPRECATED; #endif __LA_DECL int archive_errno(struct archive *); @@ -809,14 +925,116 @@ __LA_DECL void archive_copy_error(struct archive *dest, struct archive *src); __LA_DECL int archive_file_count(struct archive *); +/* + * ARCHIVE_MATCH API + */ +__LA_DECL struct archive *archive_match_new(void); +__LA_DECL int archive_match_free(struct archive *); + +/* + * Test if archive_entry is excluded. + * This is a convenience function. This is the same as calling all + * archive_match_path_excluded, archive_match_time_excluded + * and archive_match_owner_excluded. + */ +__LA_DECL int archive_match_excluded(struct archive *, + struct archive_entry *); + +/* + * Test if pathname is excluded. The conditions are set by following functions. + */ +__LA_DECL int archive_match_path_excluded(struct archive *, + struct archive_entry *); +/* Add exclusion pathname pattern. */ +__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *); +__LA_DECL int archive_match_exclude_pattern_w(struct archive *, + const wchar_t *); +/* Add exclusion pathname pattern from file. */ +__LA_DECL int archive_match_exclude_pattern_from_file(struct archive *, + const char *, int _nullSeparator); +__LA_DECL int archive_match_exclude_pattern_from_file_w(struct archive *, + const wchar_t *, int _nullSeparator); +/* Add inclusion pathname pattern. */ +__LA_DECL int archive_match_include_pattern(struct archive *, const char *); +__LA_DECL int archive_match_include_pattern_w(struct archive *, + const wchar_t *); +/* Add inclusion pathname pattern from file. */ +__LA_DECL int archive_match_include_pattern_from_file(struct archive *, + const char *, int _nullSeparator); +__LA_DECL int archive_match_include_pattern_from_file_w(struct archive *, + const wchar_t *, int _nullSeparator); +/* + * How to get statistic information for inclusion patterns. + */ +/* Return the amount number of unmatched inclusion patterns. */ +__LA_DECL int archive_match_path_unmatched_inclusions(struct archive *); +/* Return the pattern of unmatched inclusion with ARCHIVE_OK. + * Return ARCHIVE_EOF if there is no inclusion pattern. */ +__LA_DECL int archive_match_path_unmatched_inclusions_next( + struct archive *, const char **); +__LA_DECL int archive_match_path_unmatched_inclusions_next_w( + struct archive *, const wchar_t **); + +/* + * Test if a file is excluded by its time stamp. + * The conditions are set by following functions. + */ +__LA_DECL int archive_match_time_excluded(struct archive *, + struct archive_entry *); + +/* + * Flags to tell a matching type of time stamps. These are used for + * following functinos. + */ +/* Time flag: mtime to be tested. */ +#define ARCHIVE_MATCH_MTIME (0x0100) +/* Time flag: ctime to be tested. */ +#define ARCHIVE_MATCH_CTIME (0x0200) +/* Comparison flag: Match the time if it is newer than. */ +#define ARCHIVE_MATCH_NEWER (0x0001) +/* Comparison flag: Match the time if it is older than. */ +#define ARCHIVE_MATCH_OLDER (0x0002) +/* Comparison flag: Match the time if it is equal to. */ +#define ARCHIVE_MATCH_EQUAL (0x0010) +/* Set inclusion time. */ +__LA_DECL int archive_match_include_time(struct archive *, int _flag, + time_t _sec, long _nsec); +/* Set inclusion time by a date string. */ +__LA_DECL int archive_match_include_date(struct archive *, int _flag, + const char *_datestr); +__LA_DECL int archive_match_include_date_w(struct archive *, int _flag, + const wchar_t *_datestr); +/* Set inclusion time by a particluar file. */ +__LA_DECL int archive_match_include_file_time(struct archive *, + int _flag, const char *_pathname); +__LA_DECL int archive_match_include_file_time_w(struct archive *, + int _flag, const wchar_t *_pathname); +/* Add exclusion entry. */ +__LA_DECL int archive_match_exclude_entry(struct archive *, + int _flag, struct archive_entry *); + +/* + * Test if a file is excluded by its uid ,gid, uname or gname. + * The conditions are set by following functions. + */ +__LA_DECL int archive_match_owner_excluded(struct archive *, + struct archive_entry *); +/* Add inclusion uid, gid, uname and gname. */ +__LA_DECL int archive_match_include_uid(struct archive *, __LA_INT64_T); +__LA_DECL int archive_match_include_gid(struct archive *, __LA_INT64_T); +__LA_DECL int archive_match_include_uname(struct archive *, const char *); +__LA_DECL int archive_match_include_uname_w(struct archive *, + const wchar_t *); +__LA_DECL int archive_match_include_gname(struct archive *, const char *); +__LA_DECL int archive_match_include_gname_w(struct archive *, + const wchar_t *); + #ifdef __cplusplus } #endif /* These are meaningless outside of this header. */ #undef __LA_DECL -#undef __LA_GID_T -#undef __LA_UID_T /* These need to remain defined because they're used in the * callback type definitions. XXX Fix this. This is ugly. XXX */ diff --git a/Utilities/cmlibarchive/libarchive/archive_acl.c b/Utilities/cmlibarchive/libarchive/archive_acl.c index 4747a4c5a..bf4b61040 100644 --- a/Utilities/cmlibarchive/libarchive/archive_acl.c +++ b/Utilities/cmlibarchive/libarchive/archive_acl.c @@ -52,6 +52,9 @@ static int acl_special(struct archive_acl *acl, int type, int permset, int tag); static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl, int type, int permset, int tag, int id); +static int archive_acl_add_entry_len_l(struct archive_acl *acl, + int type, int permset, int tag, int id, const char *name, + size_t len, struct archive_string_conv *sc); static int isint_w(const wchar_t *start, const wchar_t *end, int *result); static int ismode_w(const wchar_t *start, const wchar_t *end, int *result); static void next_field_w(const wchar_t **wp, const wchar_t **start, @@ -65,7 +68,7 @@ static int isint(const char *start, const char *end, int *result); static int ismode(const char *start, const char *end, int *result); static void next_field(const char **p, const char **start, const char **end, char *sep); -static int prefix(const char *start, const char *end, +static int prefix_c(const char *start, const char *end, const char *test); static void append_entry(char **p, const char *prefix, int tag, const char *name, int perm, int id); @@ -152,7 +155,7 @@ archive_acl_add_entry_w_len(struct archive_acl *acl, return ARCHIVE_OK; } -int +static int archive_acl_add_entry_len_l(struct archive_acl *acl, int type, int permset, int tag, int id, const char *name, size_t len, struct archive_string_conv *sc) @@ -419,8 +422,11 @@ archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int *permset = acl->acl_p->permset; *tag = acl->acl_p->tag; *id = acl->acl_p->id; - if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0) + if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0) { + if (errno == ENOMEM) + return (ARCHIVE_FATAL); *name = NULL; + } acl->acl_p = acl->acl_p->next; return (ARCHIVE_OK); } @@ -438,7 +444,7 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags) const wchar_t *prefix; wchar_t separator; struct archive_acl_entry *ap; - int id; + int id, r; wchar_t *wp; if (acl->acl_text_w != NULL) { @@ -458,9 +464,11 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags) length += 8; /* "default:" */ length += 5; /* tag name */ length += 1; /* colon */ - if (archive_mstring_get_wcs(a, &ap->name, &wname) == 0 && - wname != NULL) + r = archive_mstring_get_wcs(a, &ap->name, &wname); + if (r == 0 && wname != NULL) length += wcslen(wname); + else if (r < 0 && errno == ENOMEM) + return (NULL); else length += sizeof(uid_t) * 3 + 1; length ++; /* colon */ @@ -484,7 +492,7 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags) /* Now, allocate the string and actually populate it. */ wp = acl->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t)); if (wp == NULL) - __archive_errx(1, "No memory to generate the text version of the ACL"); + return (NULL); count = 0; if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, @@ -499,16 +507,19 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags) ap = acl->acl_head; while (ap != NULL) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0 && - archive_mstring_get_wcs(a, &ap->name, &wname) == 0) { - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry_w(&wp, NULL, ap->tag, wname, - ap->permset, id); - count++; + if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + r = archive_mstring_get_wcs(a, &ap->name, &wname); + if (r == 0) { + *wp++ = separator; + if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) + id = ap->id; + else + id = -1; + append_entry_w(&wp, NULL, ap->tag, wname, + ap->permset, id); + count++; + } else if (r < 0 && errno == ENOMEM) + return (NULL); } ap = ap->next; } @@ -523,17 +534,20 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags) ap = acl->acl_head; count = 0; while (ap != NULL) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0 && - archive_mstring_get_wcs(a, &ap->name, &wname) == 0) { - if (count > 0) - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry_w(&wp, prefix, ap->tag, - wname, ap->permset, id); - count ++; + if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { + r = archive_mstring_get_wcs(a, &ap->name, &wname); + if (r == 0) { + if (count > 0) + *wp++ = separator; + if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) + id = ap->id; + else + id = -1; + append_entry_w(&wp, prefix, ap->tag, + wname, ap->permset, id); + count ++; + } else if (r < 0 && errno == ENOMEM) + return (NULL); } ap = ap->next; } @@ -672,7 +686,7 @@ archive_acl_text_l(struct archive_acl *acl, int flags, /* Now, allocate the string and actually populate it. */ p = acl->acl_text = (char *)malloc(length); if (p == NULL) - __archive_errx(1, "No memory to generate the text version of the ACL"); + return (-1); count = 0; if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, @@ -1088,7 +1102,7 @@ archive_acl_parse_l(struct archive_acl *acl, type = default_type; name.start = name.end = NULL; - if (prefix(field[0].start, field[0].end, "user")) { + if (prefix_c(field[0].start, field[0].end, "user")) { if (!ismode(field[2].start, field[2].end, &permset)) return (ARCHIVE_WARN); if (id != -1 || field[1].start < field[1].end) { @@ -1096,7 +1110,7 @@ archive_acl_parse_l(struct archive_acl *acl, name = field[1]; } else tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - } else if (prefix(field[0].start, field[0].end, "group")) { + } else if (prefix_c(field[0].start, field[0].end, "group")) { if (!ismode(field[2].start, field[2].end, &permset)) return (ARCHIVE_WARN); if (id != -1 || field[1].start < field[1].end) { @@ -1104,7 +1118,7 @@ archive_acl_parse_l(struct archive_acl *acl, name = field[1]; } else tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - } else if (prefix(field[0].start, field[0].end, "other")) { + } else if (prefix_c(field[0].start, field[0].end, "other")) { if (fields == 2 && field[1].start < field[1].end && ismode(field[1].start, field[1].end, &permset)) { @@ -1117,7 +1131,7 @@ archive_acl_parse_l(struct archive_acl *acl, } else return (ARCHIVE_WARN); tag = ARCHIVE_ENTRY_ACL_OTHER; - } else if (prefix(field[0].start, field[0].end, "mask")) { + } else if (prefix_c(field[0].start, field[0].end, "mask")) { if (fields == 2 && field[1].start < field[1].end && ismode(field[1].start, field[1].end, &permset)) { @@ -1246,7 +1260,7 @@ next_field(const char **p, const char **start, * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc. */ static int -prefix(const char *start, const char *end, const char *test) +prefix_c(const char *start, const char *end, const char *test) { if (start == end) return (0); diff --git a/Utilities/cmlibarchive/libarchive/archive_check_magic.c b/Utilities/cmlibarchive/libarchive/archive_check_magic.c index 91229557a..c695e582a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_check_magic.c +++ b/Utilities/cmlibarchive/libarchive/archive_check_magic.c @@ -94,6 +94,7 @@ archive_handle_type_name(unsigned m) case ARCHIVE_READ_MAGIC: return ("archive_read"); case ARCHIVE_WRITE_DISK_MAGIC: return ("archive_write_disk"); case ARCHIVE_READ_DISK_MAGIC: return ("archive_read_disk"); + case ARCHIVE_MATCH_MAGIC: return ("archive_match"); default: return NULL; } } diff --git a/Utilities/cmlibarchive/libarchive/archive_cmdline.c b/Utilities/cmlibarchive/libarchive/archive_cmdline.c new file mode 100644 index 000000000..7d3bac53b --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_cmdline.c @@ -0,0 +1,227 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_STRING_H +# include <string.h> +#endif +#ifdef HAVE_STDLIB_H +# include <stdlib.h> +#endif + +#include "archive.h" +#include "archive_cmdline_private.h" +#include "archive_string.h" + +static int cmdline_set_path(struct archive_cmdline *, const char *); +static int cmdline_add_arg(struct archive_cmdline *, const char *); + +static ssize_t +extract_quotation(struct archive_string *as, const char *p) +{ + const char *s; + + for (s = p + 1; *s;) { + if (*s == '\\') { + if (s[1] != '\0') { + archive_strappend_char(as, s[1]); + s += 2; + } else + s++; + } else if (*s == '"') + break; + else { + archive_strappend_char(as, s[0]); + s++; + } + } + if (*s != '"') + return (ARCHIVE_FAILED);/* Invalid sequence. */ + return ((ssize_t)(s + 1 - p)); +} + +static ssize_t +get_argument(struct archive_string *as, const char *p) +{ + const char *s = p; + + archive_string_empty(as); + + /* Skip beginning space characters. */ + while (*s != '\0' && *s == ' ') + s++; + /* Copy non-space characters. */ + while (*s != '\0' && *s != ' ') { + if (*s == '\\') { + if (s[1] != '\0') { + archive_strappend_char(as, s[1]); + s += 2; + } else { + s++;/* Ignore this character.*/ + break; + } + } else if (*s == '"') { + ssize_t q = extract_quotation(as, s); + if (q < 0) + return (ARCHIVE_FAILED);/* Invalid sequence. */ + s += q; + } else { + archive_strappend_char(as, s[0]); + s++; + } + } + return ((ssize_t)(s - p)); +} + +/* + * Set up command line arguments. + * Returns ARChIVE_OK if everything okey. + * Returns ARChIVE_FAILED if there is a lack of the `"' terminator or an + * empty command line. + * Returns ARChIVE_FATAL if no memory. + */ +int +__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd) +{ + struct archive_string as; + const char *p; + ssize_t al; + int r; + + archive_string_init(&as); + + /* Get first argument as a command path. */ + al = get_argument(&as, cmd); + if (al < 0) { + r = ARCHIVE_FAILED;/* Invalid sequence. */ + goto exit_function; + } + if (archive_strlen(&as) == 0) { + r = ARCHIVE_FAILED;/* An empty command path. */ + goto exit_function; + } + r = cmdline_set_path(data, as.s); + if (r != ARCHIVE_OK) + goto exit_function; + p = strrchr(as.s, '/'); + if (p == NULL) + p = as.s; + else + p++; + r = cmdline_add_arg(data, p); + if (r != ARCHIVE_OK) + goto exit_function; + cmd += al; + + for (;;) { + al = get_argument(&as, cmd); + if (al < 0) { + r = ARCHIVE_FAILED;/* Invalid sequence. */ + goto exit_function; + } + if (al == 0) + break; + cmd += al; + if (archive_strlen(&as) == 0 && *cmd == '\0') + break; + r = cmdline_add_arg(data, as.s); + if (r != ARCHIVE_OK) + goto exit_function; + } + r = ARCHIVE_OK; +exit_function: + archive_string_free(&as); + return (r); +} + +/* + * Set the program path. + */ +static int +cmdline_set_path(struct archive_cmdline *data, const char *path) +{ + char *newptr; + + newptr = realloc(data->path, strlen(path) + 1); + if (newptr == NULL) + return (ARCHIVE_FATAL); + data->path = newptr; + strcpy(data->path, path); + return (ARCHIVE_OK); +} + +/* + * Add a argument for the program. + */ +static int +cmdline_add_arg(struct archive_cmdline *data, const char *arg) +{ + char **newargv; + + if (data->path == NULL) + return (ARCHIVE_FAILED); + + newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *)); + if (newargv == NULL) + return (ARCHIVE_FATAL); + data->argv = newargv; + data->argv[data->argc] = strdup(arg); + if (data->argv[data->argc] == NULL) + return (ARCHIVE_FATAL); + /* Set the terminator of argv. */ + data->argv[++data->argc] = NULL; + return (ARCHIVE_OK); +} + +struct archive_cmdline * +__archive_cmdline_allocate(void) +{ + return (struct archive_cmdline *) + calloc(1, sizeof(struct archive_cmdline)); +} + +/* + * Release the resources. + */ +int +__archive_cmdline_free(struct archive_cmdline *data) +{ + + if (data) { + free(data->path); + if (data->argv != NULL) { + int i; + for (i = 0; data->argv[i] != NULL; i++) + free(data->argv[i]); + free(data->argv); + } + free(data); + } + return (ARCHIVE_OK); +} + diff --git a/Utilities/cmlibarchive/libarchive/archive_cmdline_private.h b/Utilities/cmlibarchive/libarchive/archive_cmdline_private.h new file mode 100644 index 000000000..4e409e814 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_cmdline_private.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __LIBARCHIVE_BUILD +#ifndef __LIBARCHIVE_TEST +#error This header is only to be used internally to libarchive. +#endif +#endif + +#ifndef ARCHIVE_CMDLINE_PRIVATE_H +#define ARCHIVE_CMDLINE_PRIVATE_H + +struct archive_cmdline { + char *path; + char **argv; + int argc; +}; + +struct archive_cmdline *__archive_cmdline_allocate(void); +int __archive_cmdline_parse(struct archive_cmdline *, const char *); +int __archive_cmdline_free(struct archive_cmdline *); + +#endif diff --git a/Utilities/cmlibarchive/libarchive/archive_crypto.c b/Utilities/cmlibarchive/libarchive/archive_crypto.c index 2caf57169..85aba3ae2 100644 --- a/Utilities/cmlibarchive/libarchive/archive_crypto.c +++ b/Utilities/cmlibarchive/libarchive/archive_crypto.c @@ -90,7 +90,7 @@ win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len) static int win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx) { - DWORD siglen = bufsize; + DWORD siglen = (DWORD)bufsize; if (!ctx->valid) return (ARCHIVE_FAILED); @@ -1222,8 +1222,10 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md) * 2. libc2 * 3. libc3 * 4. libSystem - * 5. OpenSSL - * 6. Windows API + * 5. Nettle + * 6. OpenSSL + * 7. libmd + * 8. Windows API */ const struct archive_crypto __archive_crypto = { diff --git a/Utilities/cmlibarchive/libarchive/archive_endian.h b/Utilities/cmlibarchive/libarchive/archive_endian.h index 3c039f702..1c48563b1 100644 --- a/Utilities/cmlibarchive/libarchive/archive_endian.h +++ b/Utilities/cmlibarchive/libarchive/archive_endian.h @@ -160,8 +160,8 @@ archive_be64enc(void *pp, uint64_t u) { unsigned char *p = (unsigned char *)pp; - archive_be32enc(p, u >> 32); - archive_be32enc(p + 4, u & 0xffffffff); + archive_be32enc(p, (uint32_t)(u >> 32)); + archive_be32enc(p + 4, (uint32_t)(u & 0xffffffff)); } static inline void @@ -189,8 +189,8 @@ archive_le64enc(void *pp, uint64_t u) { unsigned char *p = (unsigned char *)pp; - archive_le32enc(p, u & 0xffffffff); - archive_le32enc(p + 4, u >> 32); + archive_le32enc(p, (uint32_t)(u & 0xffffffff)); + archive_le32enc(p + 4, (uint32_t)(u >> 32)); } #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.3 b/Utilities/cmlibarchive/libarchive/archive_entry.3 index 10e3c34cc..f77f385f2 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry.3 @@ -23,9 +23,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $ +.\" $FreeBSD$ .\" -.Dd Feburary 22, 2010 +.Dd Feburary 2, 2012 .Dt ARCHIVE_ENTRY 3 .Os .Sh NAME @@ -34,6 +34,8 @@ .Nm archive_entry_free , .Nm archive_entry_new , .Nd functions for managing archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive_entry.h .Ft "struct archive_entry *" diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.c b/Utilities/cmlibarchive/libarchive/archive_entry.c index cbdda8a44..386e51d47 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.c +++ b/Utilities/cmlibarchive/libarchive/archive_entry.c @@ -375,8 +375,11 @@ archive_entry_fflags_text(struct archive_entry *entry) char *p; if (archive_mstring_get_mbs(entry->archive, - &entry->ae_fflags_text, &f) == 0 && f != NULL) - return (f); + &entry->ae_fflags_text, &f) == 0) { + if (f != NULL) + return (f); + } else if (errno == ENOMEM) + __archive_errx(1, "No memory"); if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0) return (NULL); @@ -390,6 +393,8 @@ archive_entry_fflags_text(struct archive_entry *entry) if (archive_mstring_get_mbs(entry->archive, &entry->ae_fflags_text, &f) == 0) return (f); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -405,6 +410,8 @@ archive_entry_gname(struct archive_entry *entry) const char *p; if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -414,6 +421,8 @@ archive_entry_gname_w(struct archive_entry *entry) const wchar_t *p; if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -428,9 +437,13 @@ const char * archive_entry_hardlink(struct archive_entry *entry) { const char *p; - if ((entry->ae_set & AE_SET_HARDLINK) && archive_mstring_get_mbs( + if ((entry->ae_set & AE_SET_HARDLINK) == 0) + return (NULL); + if (archive_mstring_get_mbs( entry->archive, &entry->ae_hardlink, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -438,9 +451,13 @@ const wchar_t * archive_entry_hardlink_w(struct archive_entry *entry) { const wchar_t *p; - if ((entry->ae_set & AE_SET_HARDLINK) && archive_mstring_get_wcs( + if ((entry->ae_set & AE_SET_HARDLINK) == 0) + return (NULL); + if (archive_mstring_get_wcs( entry->archive, &entry->ae_hardlink, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -511,6 +528,8 @@ archive_entry_pathname(struct archive_entry *entry) if (archive_mstring_get_mbs( entry->archive, &entry->ae_pathname, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -521,6 +540,8 @@ archive_entry_pathname_w(struct archive_entry *entry) if (archive_mstring_get_wcs( entry->archive, &entry->ae_pathname, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -584,6 +605,8 @@ archive_entry_sourcepath(struct archive_entry *entry) if (archive_mstring_get_mbs( entry->archive, &entry->ae_sourcepath, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -601,9 +624,13 @@ const char * archive_entry_symlink(struct archive_entry *entry) { const char *p; - if ((entry->ae_set & AE_SET_SYMLINK) && archive_mstring_get_mbs( + if ((entry->ae_set & AE_SET_SYMLINK) == 0) + return (NULL); + if (archive_mstring_get_mbs( entry->archive, &entry->ae_symlink, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -611,9 +638,13 @@ const wchar_t * archive_entry_symlink_w(struct archive_entry *entry) { const wchar_t *p; - if ((entry->ae_set & AE_SET_SYMLINK) && archive_mstring_get_wcs( + if ((entry->ae_set & AE_SET_SYMLINK) == 0) + return (NULL); + if (archive_mstring_get_wcs( entry->archive, &entry->ae_symlink, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -641,6 +672,8 @@ archive_entry_uname(struct archive_entry *entry) const char *p; if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -650,6 +683,8 @@ archive_entry_uname_w(struct archive_entry *entry) const wchar_t *p; if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0) return (p); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); } @@ -730,6 +765,8 @@ archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name) if (archive_mstring_update_utf8(entry->archive, &entry->ae_gname, name) == 0) return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (0); } @@ -796,6 +833,8 @@ archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *targ if (archive_mstring_update_utf8(entry->archive, &entry->ae_hardlink, target) == 0) return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (0); } @@ -932,7 +971,11 @@ archive_entry_update_link_utf8(struct archive_entry *entry, const char *target) else r = archive_mstring_update_utf8(entry->archive, &entry->ae_hardlink, target); - return ((r == 0)? 1: 0); + if (r == 0) + return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (0); } int @@ -1005,6 +1048,8 @@ archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name if (archive_mstring_update_utf8(entry->archive, &entry->ae_pathname, name) == 0) return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (0); } @@ -1115,6 +1160,8 @@ archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkn if (archive_mstring_update_utf8(entry->archive, &entry->ae_symlink, linkname) == 0) return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (0); } @@ -1164,6 +1211,8 @@ archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name) if (archive_mstring_update_utf8(entry->archive, &entry->ae_uname, name) == 0) return (1); + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (0); } @@ -1269,7 +1318,12 @@ int archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type, int *permset, int *tag, int *id, const char **name) { - return archive_acl_next(entry->archive, &entry->acl, want_type, type, permset, tag, id, name); + int r; + r = archive_acl_next(entry->archive, &entry->acl, want_type, type, + permset, tag, id, name); + if (r == ARCHIVE_FATAL && errno == ENOMEM) + __archive_errx(1, "No memory"); + return (r); } /* @@ -1279,7 +1333,11 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type, const wchar_t * archive_entry_acl_text_w(struct archive_entry *entry, int flags) { - return archive_acl_text_w(entry->archive, &entry->acl, flags); + const wchar_t *r; + r = archive_acl_text_w(entry->archive, &entry->acl, flags); + if (r == NULL && errno == ENOMEM) + __archive_errx(1, "No memory"); + return (r); } const char * @@ -1288,7 +1346,7 @@ archive_entry_acl_text(struct archive_entry *entry, int flags) const char *p; if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0 && errno == ENOMEM) - return (NULL); + __archive_errx(1, "No memory"); return (p); } @@ -1391,6 +1449,9 @@ static struct flag { { "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 }, { "nouunlink", L"nouunlink", UF_NOUNLINK, 0 }, #endif +#ifdef UF_COMPRESSED + { "nocompressed",L"nocompressed", UF_COMPRESSED, 0 }, +#endif #ifdef EXT2_UNRM_FL { "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0}, #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h index 9c44e25f8..85ea885f7 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry.h @@ -29,7 +29,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3000002 +#define ARCHIVE_VERSION_NUMBER 3001002 /* * Note: archive_entry.h is for use outside of libarchive; the @@ -47,21 +47,9 @@ #include <windows.h> #endif -/* Get appropriate definitions of standard POSIX-style types. */ -/* These should match the types used in 'struct stat' */ +/* Get a suitable 64-bit integer type. */ #if defined(_WIN32) && !defined(__CYGWIN__) -#define __LA_INT64_T __int64 -# if defined(__BORLANDC__) -# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */ -# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */ -# define __LA_DEV_T dev_t -# define __LA_MODE_T mode_t -# else -# define __LA_UID_T short /* Remove in libarchive 3.2 */ -# define __LA_GID_T short /* Remove in libarchive 3.2 */ -# define __LA_DEV_T unsigned int -# define __LA_MODE_T unsigned short -# endif +# define __LA_INT64_T __int64 #else #include <unistd.h> # if defined(_SCO_DS) || defined(__osf__) @@ -69,17 +57,17 @@ # else # define __LA_INT64_T int64_t # endif -# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */ -# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */ -# define __LA_DEV_T dev_t -# define __LA_MODE_T mode_t #endif -/* - * Remove this for libarchive 3.2, since ino_t is no longer used. - */ -#define __LA_INO_T ino_t - +/* Get a suitable definition for mode_t */ +#if ARCHIVE_VERSION_NUMBER >= 3999000 +/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ +# define __LA_MODE_T int +#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) +# define __LA_MODE_T unsigned short +#else +# define __LA_MODE_T mode_t +#endif /* * On Windows, define LIBARCHIVE_STATIC if you're building or using a @@ -149,6 +137,10 @@ struct archive_entry; * portable values to platform-native values when entries are read from * or written to disk. */ +/* + * In libarchive 4.0, we can drop the casts here. + * They're needed to work around Borland C's broken mode_t. + */ #define AE_IFMT ((__LA_MODE_T)0170000) #define AE_IFREG ((__LA_MODE_T)0100000) #define AE_IFLNK ((__LA_MODE_T)0120000) @@ -321,7 +313,10 @@ __LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char * manipulate archives on systems different than the ones they were * created on. * - * TODO: On Linux, provide both stat32 and stat64 versions of these functions. + * TODO: On Linux and other LFS systems, provide both stat32 and + * stat64 versions of these functions and all of the macro glue so + * that archive_entry_stat is magically defined to + * archive_entry_stat32 or archive_entry_stat64 as appropriate. */ __LA_DECL const struct stat *archive_entry_stat(struct archive_entry *); __LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *); diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 index 93906e798..f5c337733 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 21, 2010 +.Dd February 2, 2012 .Dt ARCHIVE_ENTRY_ACL 3 .Os .Sh NAME @@ -35,6 +35,8 @@ .Nm archive_entry_acl_reset , .Nm archive_entry_acl_text_w .Nd functions for manipulating Access Control Lists in archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive_entry.h .Ft void @@ -132,7 +134,7 @@ All files have an access ACL This specifies the permissions required for access to the file itself. Directories have an additional ACL .Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT , -which controlls the initial access ACL for newly created directory entries. +which controls the initial access ACL for newly created directory entries. .Pp .Fn archive_entry_acl_add_entry and diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c b/Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c index 7a4bc9cd0..77bf38e45 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c +++ b/Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c @@ -34,7 +34,7 @@ __FBSDID("$FreeBSD$"); #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) __inline static void -fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns) +fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns) { ULARGE_INTEGER utc; @@ -42,10 +42,10 @@ fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns) utc.LowPart = filetime->dwLowDateTime; if (utc.QuadPart >= EPOC_TIME) { utc.QuadPart -= EPOC_TIME; - *time = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */ + *t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */ *ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */ } else { - *time = 0; + *t = 0; *ns = 0; } } diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c b/Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c index a18144dd5..c7d59497a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c +++ b/Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c @@ -244,6 +244,9 @@ archive_entry_linkify(struct archive_entry_linkresolver *res, * for future use. */ le = insert_entry(res, *e); + if (le == NULL) + /* XXX We should return an error code XXX */ + return; le->entry = *e; *e = NULL; } @@ -362,7 +365,7 @@ insert_entry(struct archive_entry_linkresolver *res, if (res->number_entries > res->number_buckets * 2) grow_hash(res); - hash = archive_entry_dev(entry) ^ archive_entry_ino64(entry); + hash = (size_t)(archive_entry_dev(entry) ^ archive_entry_ino64(entry)); bucket = hash & (res->number_buckets - 1); /* If we could allocate the entry, record it. */ diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_linkify.3 b/Utilities/cmlibarchive/libarchive/archive_entry_linkify.3 index a34b095e7..8c19fddb6 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_linkify.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry_linkify.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 20, 2010 +.Dd February 2, 2012 .Dt ARCHIVE_ENTRY_LINKIFY 3 .Os .Sh NAME @@ -33,7 +33,7 @@ .Nm archive_entry_linkify .Nd hardlink resolver functions .Sh LIBRARY -.Lb libarchive +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive_entry.h .Ft struct archive_entry_linkresolver * diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_paths.3 b/Utilities/cmlibarchive/libarchive/archive_entry_paths.3 index 621f65518..51c8b8c8e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_paths.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry_paths.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 22, 2010 +.Dd February 2, 2012 .Dt ARCHIVE_ENTRY_PATHS 3 .Os .Sh NAME @@ -51,6 +51,8 @@ .Nm archive_entry_copy_symlink_w , .Nm archve_entry_update_symlink_utf8 .Nd functions for manipulating path names in archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive_entry.h .Ft const char * diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_perms.3 b/Utilities/cmlibarchive/libarchive/archive_entry_perms.3 index 164af9731..5b7b5d955 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_perms.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry_perms.3 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 22, 2010 +.Dd February 2, 2012 .Dt ARCHIVE_ENTRY_PERMS 3 .Os .Sh NAME @@ -52,6 +52,8 @@ .Nm archive_entry_copy_fflags_text , .Nm archive_entry_copy_fflags_text_w .Nd functions for manipulating ownership and permissions in archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive_entry.h .Ft gid_t diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_stat.3 b/Utilities/cmlibarchive/libarchive/archive_entry_stat.3 index 36a7efb23..84a4ea12a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_stat.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry_stat.3 @@ -22,8 +22,8 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 12, 2008 -.Dt ARCHIVE_ENTRY 3 +.Dd February 2, 2012 +.Dt ARCHIVE_ENTRY_STAT 3 .Os .Sh NAME .Nm archive_entry_stat , @@ -56,6 +56,8 @@ .Nm archive_entry_rdevminor , .Nm archive_entry_set_rdevminor , .Nd accessor functions for manipulating archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive_entry.h .Ft const struct stat * diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_stat.c b/Utilities/cmlibarchive/libarchive/archive_entry_stat.c index d5ed1cb13..71a407b1f 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_stat.c +++ b/Utilities/cmlibarchive/libarchive/archive_entry_stat.c @@ -70,12 +70,12 @@ archive_entry_stat(struct archive_entry *entry) st->st_ctime = archive_entry_ctime(entry); st->st_mtime = archive_entry_mtime(entry); st->st_dev = archive_entry_dev(entry); - st->st_gid = archive_entry_gid(entry); - st->st_uid = archive_entry_uid(entry); - st->st_ino = archive_entry_ino64(entry); + st->st_gid = (gid_t)archive_entry_gid(entry); + st->st_uid = (uid_t)archive_entry_uid(entry); + st->st_ino = (ino_t)archive_entry_ino64(entry); st->st_nlink = archive_entry_nlink(entry); st->st_rdev = archive_entry_rdev(entry); - st->st_size = archive_entry_size(entry); + st->st_size = (off_t)archive_entry_size(entry); st->st_mode = archive_entry_mode(entry); /* @@ -110,7 +110,7 @@ archive_entry_stat(struct archive_entry *entry) /* * TODO: On Linux, store 32 or 64 here depending on whether * the cached stat structure is a stat32 or a stat64. This - * will allow us to support both variants interchangably. + * will allow us to support both variants interchangeably. */ entry->stat_valid = 1; diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_time.3 b/Utilities/cmlibarchive/libarchive/archive_entry_time.3 index 85a8209e8..17c658a65 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_time.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry_time.3 @@ -23,9 +23,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $ +.\" $FreeBSD$ .\" -.Dd February 21, 2010 +.Dd February 2, 2012 .Dt ARCHIVE_ENTRY_TIME 3 .Os .Sh NAME @@ -50,6 +50,8 @@ .Nm archive_entry_set_mtime , .Nm archive_entry_unset_mtime , .Nd functions for manipulating times in archive entry descriptions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive_entry.h .Ft time_t diff --git a/Utilities/cmlibarchive/libarchive/archive_getdate.c b/Utilities/cmlibarchive/libarchive/archive_getdate.c new file mode 100644 index 000000000..f8b5a28d5 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_getdate.c @@ -0,0 +1,1037 @@ +/* + * This code is in the public domain and has no copyright. + * + * This is a plain C recursive-descent translation of an old + * public-domain YACC grammar that has been used for parsing dates in + * very many open-source projects. + * + * Since the original authors were generous enough to donate their + * work to the public domain, I feel compelled to match their + * generosity. + * + * Tim Kientzle, February 2009. + */ + +/* + * Header comment from original getdate.y: + */ + +/* +** Originally written by Steven M. Bellovin <smb@research.att.com> while +** at the University of North Carolina at Chapel Hill. Later tweaked by +** a couple of people on Usenet. Completely overhauled by Rich $alz +** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990; +** +** This grammar has 10 shift/reduce conflicts. +** +** This code is in the public domain and has no copyright. +*/ + +#ifdef __FreeBSD__ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#endif + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +/* This file defines a single public function. */ +time_t __archive_get_date(time_t now, char *); + +/* Basic time units. */ +#define EPOCH 1970 +#define MINUTE (60L) +#define HOUR (60L * MINUTE) +#define DAY (24L * HOUR) + +/* Daylight-savings mode: on, off, or not yet known. */ +enum DSTMODE { DSTon, DSToff, DSTmaybe }; +/* Meridian: am or pm. */ +enum { tAM, tPM }; +/* Token types returned by nexttoken() */ +enum { tAGO = 260, tDAY, tDAYZONE, tAMPM, tMONTH, tMONTH_UNIT, tSEC_UNIT, + tUNUMBER, tZONE, tDST }; +struct token { int token; time_t value; }; + +/* + * Parser state. + */ +struct gdstate { + struct token *tokenp; /* Pointer to next token. */ + /* HaveXxxx counts how many of this kind of phrase we've seen; + * it's a fatal error to have more than one time, zone, day, + * or date phrase. */ + int HaveYear; + int HaveMonth; + int HaveDay; + int HaveWeekDay; /* Day of week */ + int HaveTime; /* Hour/minute/second */ + int HaveZone; /* timezone and/or DST info */ + int HaveRel; /* time offset; we can have more than one */ + /* Absolute time values. */ + time_t Timezone; /* Seconds offset from GMT */ + time_t Day; + time_t Hour; + time_t Minutes; + time_t Month; + time_t Seconds; + time_t Year; + /* DST selection */ + enum DSTMODE DSTmode; + /* Day of week accounting, e.g., "3rd Tuesday" */ + time_t DayOrdinal; /* "3" in "3rd Tuesday" */ + time_t DayNumber; /* "Tuesday" in "3rd Tuesday" */ + /* Relative time values: hour/day/week offsets are measured in + * seconds, month/year are counted in months. */ + time_t RelMonth; + time_t RelSeconds; +}; + +/* + * A series of functions that recognize certain common time phrases. + * Each function returns 1 if it managed to make sense of some of the + * tokens, zero otherwise. + */ + +/* + * hour:minute or hour:minute:second with optional AM, PM, or numeric + * timezone offset + */ +static int +timephrase(struct gdstate *gds) +{ + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == ':' + && gds->tokenp[2].token == tUNUMBER + && gds->tokenp[3].token == ':' + && gds->tokenp[4].token == tUNUMBER) { + /* "12:14:18" or "22:08:07" */ + ++gds->HaveTime; + gds->Hour = gds->tokenp[0].value; + gds->Minutes = gds->tokenp[2].value; + gds->Seconds = gds->tokenp[4].value; + gds->tokenp += 5; + } + else if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == ':' + && gds->tokenp[2].token == tUNUMBER) { + /* "12:14" or "22:08" */ + ++gds->HaveTime; + gds->Hour = gds->tokenp[0].value; + gds->Minutes = gds->tokenp[2].value; + gds->Seconds = 0; + gds->tokenp += 3; + } + else if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tAMPM) { + /* "7" is a time if it's followed by "am" or "pm" */ + ++gds->HaveTime; + gds->Hour = gds->tokenp[0].value; + gds->Minutes = gds->Seconds = 0; + /* We'll handle the AM/PM below. */ + gds->tokenp += 1; + } else { + /* We can't handle this. */ + return 0; + } + + if (gds->tokenp[0].token == tAMPM) { + /* "7:12pm", "12:20:13am" */ + if (gds->Hour == 12) + gds->Hour = 0; + if (gds->tokenp[0].value == tPM) + gds->Hour += 12; + gds->tokenp += 1; + } + if (gds->tokenp[0].token == '+' + && gds->tokenp[1].token == tUNUMBER) { + /* "7:14+0700" */ + gds->HaveZone++; + gds->DSTmode = DSToff; + gds->Timezone = - ((gds->tokenp[1].value / 100) * HOUR + + (gds->tokenp[1].value % 100) * MINUTE); + gds->tokenp += 2; + } + if (gds->tokenp[0].token == '-' + && gds->tokenp[1].token == tUNUMBER) { + /* "19:14:12-0530" */ + gds->HaveZone++; + gds->DSTmode = DSToff; + gds->Timezone = + ((gds->tokenp[1].value / 100) * HOUR + + (gds->tokenp[1].value % 100) * MINUTE); + gds->tokenp += 2; + } + return 1; +} + +/* + * Timezone name, possibly including DST. + */ +static int +zonephrase(struct gdstate *gds) +{ + if (gds->tokenp[0].token == tZONE + && gds->tokenp[1].token == tDST) { + gds->HaveZone++; + gds->Timezone = gds->tokenp[0].value; + gds->DSTmode = DSTon; + gds->tokenp += 1; + return 1; + } + + if (gds->tokenp[0].token == tZONE) { + gds->HaveZone++; + gds->Timezone = gds->tokenp[0].value; + gds->DSTmode = DSToff; + gds->tokenp += 1; + return 1; + } + + if (gds->tokenp[0].token == tDAYZONE) { + gds->HaveZone++; + gds->Timezone = gds->tokenp[0].value; + gds->DSTmode = DSTon; + gds->tokenp += 1; + return 1; + } + return 0; +} + +/* + * Year/month/day in various combinations. + */ +static int +datephrase(struct gdstate *gds) +{ + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == '/' + && gds->tokenp[2].token == tUNUMBER + && gds->tokenp[3].token == '/' + && gds->tokenp[4].token == tUNUMBER) { + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + if (gds->tokenp[0].value >= 13) { + /* First number is big: 2004/01/29, 99/02/17 */ + gds->Year = gds->tokenp[0].value; + gds->Month = gds->tokenp[2].value; + gds->Day = gds->tokenp[4].value; + } else if ((gds->tokenp[4].value >= 13) + || (gds->tokenp[2].value >= 13)) { + /* Last number is big: 01/07/98 */ + /* Middle number is big: 01/29/04 */ + gds->Month = gds->tokenp[0].value; + gds->Day = gds->tokenp[2].value; + gds->Year = gds->tokenp[4].value; + } else { + /* No significant clues: 02/03/04 */ + gds->Month = gds->tokenp[0].value; + gds->Day = gds->tokenp[2].value; + gds->Year = gds->tokenp[4].value; + } + gds->tokenp += 5; + return 1; + } + + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == '/' + && gds->tokenp[2].token == tUNUMBER) { + /* "1/15" */ + gds->HaveMonth++; + gds->HaveDay++; + gds->Month = gds->tokenp[0].value; + gds->Day = gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == '-' + && gds->tokenp[2].token == tUNUMBER + && gds->tokenp[3].token == '-' + && gds->tokenp[4].token == tUNUMBER) { + /* ISO 8601 format. yyyy-mm-dd. */ + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + gds->Year = gds->tokenp[0].value; + gds->Month = gds->tokenp[2].value; + gds->Day = gds->tokenp[4].value; + gds->tokenp += 5; + return 1; + } + + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == '-' + && gds->tokenp[2].token == tMONTH + && gds->tokenp[3].token == '-' + && gds->tokenp[4].token == tUNUMBER) { + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + if (gds->tokenp[0].value > 31) { + /* e.g. 1992-Jun-17 */ + gds->Year = gds->tokenp[0].value; + gds->Month = gds->tokenp[2].value; + gds->Day = gds->tokenp[4].value; + } else { + /* e.g. 17-JUN-1992. */ + gds->Day = gds->tokenp[0].value; + gds->Month = gds->tokenp[2].value; + gds->Year = gds->tokenp[4].value; + } + gds->tokenp += 5; + return 1; + } + + if (gds->tokenp[0].token == tMONTH + && gds->tokenp[1].token == tUNUMBER + && gds->tokenp[2].token == ',' + && gds->tokenp[3].token == tUNUMBER) { + /* "June 17, 2001" */ + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + gds->Month = gds->tokenp[0].value; + gds->Day = gds->tokenp[1].value; + gds->Year = gds->tokenp[3].value; + gds->tokenp += 4; + return 1; + } + + if (gds->tokenp[0].token == tMONTH + && gds->tokenp[1].token == tUNUMBER) { + /* "May 3" */ + gds->HaveMonth++; + gds->HaveDay++; + gds->Month = gds->tokenp[0].value; + gds->Day = gds->tokenp[1].value; + gds->tokenp += 2; + return 1; + } + + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tMONTH + && gds->tokenp[2].token == tUNUMBER) { + /* "12 Sept 1997" */ + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + gds->Day = gds->tokenp[0].value; + gds->Month = gds->tokenp[1].value; + gds->Year = gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tMONTH) { + /* "12 Sept" */ + gds->HaveMonth++; + gds->HaveDay++; + gds->Day = gds->tokenp[0].value; + gds->Month = gds->tokenp[1].value; + gds->tokenp += 2; + return 1; + } + + return 0; +} + +/* + * Relative time phrase: "tomorrow", "yesterday", "+1 hour", etc. + */ +static int +relunitphrase(struct gdstate *gds) +{ + if (gds->tokenp[0].token == '-' + && gds->tokenp[1].token == tUNUMBER + && gds->tokenp[2].token == tSEC_UNIT) { + /* "-3 hours" */ + gds->HaveRel++; + gds->RelSeconds -= gds->tokenp[1].value * gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + if (gds->tokenp[0].token == '+' + && gds->tokenp[1].token == tUNUMBER + && gds->tokenp[2].token == tSEC_UNIT) { + /* "+1 minute" */ + gds->HaveRel++; + gds->RelSeconds += gds->tokenp[1].value * gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tSEC_UNIT) { + /* "1 day" */ + gds->HaveRel++; + gds->RelSeconds += gds->tokenp[1].value * gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + if (gds->tokenp[0].token == '-' + && gds->tokenp[1].token == tUNUMBER + && gds->tokenp[2].token == tMONTH_UNIT) { + /* "-3 months" */ + gds->HaveRel++; + gds->RelMonth -= gds->tokenp[1].value * gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + if (gds->tokenp[0].token == '+' + && gds->tokenp[1].token == tUNUMBER + && gds->tokenp[2].token == tMONTH_UNIT) { + /* "+5 years" */ + gds->HaveRel++; + gds->RelMonth += gds->tokenp[1].value * gds->tokenp[2].value; + gds->tokenp += 3; + return 1; + } + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tMONTH_UNIT) { + /* "2 years" */ + gds->HaveRel++; + gds->RelMonth += gds->tokenp[0].value * gds->tokenp[1].value; + gds->tokenp += 2; + return 1; + } + if (gds->tokenp[0].token == tSEC_UNIT) { + /* "now", "tomorrow" */ + gds->HaveRel++; + gds->RelSeconds += gds->tokenp[0].value; + ++gds->tokenp; + return 1; + } + if (gds->tokenp[0].token == tMONTH_UNIT) { + /* "month" */ + gds->HaveRel++; + gds->RelMonth += gds->tokenp[0].value; + gds->tokenp += 1; + return 1; + } + return 0; +} + +/* + * Day of the week specification. + */ +static int +dayphrase(struct gdstate *gds) +{ + if (gds->tokenp[0].token == tDAY) { + /* "tues", "wednesday," */ + gds->HaveWeekDay++; + gds->DayOrdinal = 1; + gds->DayNumber = gds->tokenp[0].value; + gds->tokenp += 1; + if (gds->tokenp[0].token == ',') + gds->tokenp += 1; + return 1; + } + if (gds->tokenp[0].token == tUNUMBER + && gds->tokenp[1].token == tDAY) { + /* "second tues" "3 wed" */ + gds->HaveWeekDay++; + gds->DayOrdinal = gds->tokenp[0].value; + gds->DayNumber = gds->tokenp[1].value; + gds->tokenp += 2; + return 1; + } + return 0; +} + +/* + * Try to match a phrase using one of the above functions. + * This layer also deals with a couple of generic issues. + */ +static int +phrase(struct gdstate *gds) +{ + if (timephrase(gds)) + return 1; + if (zonephrase(gds)) + return 1; + if (datephrase(gds)) + return 1; + if (dayphrase(gds)) + return 1; + if (relunitphrase(gds)) { + if (gds->tokenp[0].token == tAGO) { + gds->RelSeconds = -gds->RelSeconds; + gds->RelMonth = -gds->RelMonth; + gds->tokenp += 1; + } + return 1; + } + + /* Bare numbers sometimes have meaning. */ + if (gds->tokenp[0].token == tUNUMBER) { + if (gds->HaveTime && !gds->HaveYear && !gds->HaveRel) { + gds->HaveYear++; + gds->Year = gds->tokenp[0].value; + gds->tokenp += 1; + return 1; + } + + if(gds->tokenp[0].value > 10000) { + /* "20040301" */ + gds->HaveYear++; + gds->HaveMonth++; + gds->HaveDay++; + gds->Day= (gds->tokenp[0].value)%100; + gds->Month= (gds->tokenp[0].value/100)%100; + gds->Year = gds->tokenp[0].value/10000; + gds->tokenp += 1; + return 1; + } + + if (gds->tokenp[0].value < 24) { + gds->HaveTime++; + gds->Hour = gds->tokenp[0].value; + gds->Minutes = 0; + gds->Seconds = 0; + gds->tokenp += 1; + return 1; + } + + if ((gds->tokenp[0].value / 100 < 24) + && (gds->tokenp[0].value % 100 < 60)) { + /* "513" is same as "5:13" */ + gds->Hour = gds->tokenp[0].value / 100; + gds->Minutes = gds->tokenp[0].value % 100; + gds->Seconds = 0; + gds->tokenp += 1; + return 1; + } + } + + return 0; +} + +/* + * A dictionary of time words. + */ +static struct LEXICON { + size_t abbrev; + const char *name; + int type; + time_t value; +} const TimeWords[] = { + /* am/pm */ + { 0, "am", tAMPM, tAM }, + { 0, "pm", tAMPM, tPM }, + + /* Month names. */ + { 3, "january", tMONTH, 1 }, + { 3, "february", tMONTH, 2 }, + { 3, "march", tMONTH, 3 }, + { 3, "april", tMONTH, 4 }, + { 3, "may", tMONTH, 5 }, + { 3, "june", tMONTH, 6 }, + { 3, "july", tMONTH, 7 }, + { 3, "august", tMONTH, 8 }, + { 3, "september", tMONTH, 9 }, + { 3, "october", tMONTH, 10 }, + { 3, "november", tMONTH, 11 }, + { 3, "december", tMONTH, 12 }, + + /* Days of the week. */ + { 2, "sunday", tDAY, 0 }, + { 3, "monday", tDAY, 1 }, + { 2, "tuesday", tDAY, 2 }, + { 3, "wednesday", tDAY, 3 }, + { 2, "thursday", tDAY, 4 }, + { 2, "friday", tDAY, 5 }, + { 2, "saturday", tDAY, 6 }, + + /* Timezones: Offsets are in seconds. */ + { 0, "gmt", tZONE, 0*HOUR }, /* Greenwich Mean */ + { 0, "ut", tZONE, 0*HOUR }, /* Universal (Coordinated) */ + { 0, "utc", tZONE, 0*HOUR }, + { 0, "wet", tZONE, 0*HOUR }, /* Western European */ + { 0, "bst", tDAYZONE, 0*HOUR }, /* British Summer */ + { 0, "wat", tZONE, 1*HOUR }, /* West Africa */ + { 0, "at", tZONE, 2*HOUR }, /* Azores */ + /* { 0, "bst", tZONE, 3*HOUR }, */ /* Brazil Standard: Conflict */ + /* { 0, "gst", tZONE, 3*HOUR }, */ /* Greenland Standard: Conflict*/ + { 0, "nft", tZONE, 3*HOUR+30*MINUTE }, /* Newfoundland */ + { 0, "nst", tZONE, 3*HOUR+30*MINUTE }, /* Newfoundland Standard */ + { 0, "ndt", tDAYZONE, 3*HOUR+30*MINUTE }, /* Newfoundland Daylight */ + { 0, "ast", tZONE, 4*HOUR }, /* Atlantic Standard */ + { 0, "adt", tDAYZONE, 4*HOUR }, /* Atlantic Daylight */ + { 0, "est", tZONE, 5*HOUR }, /* Eastern Standard */ + { 0, "edt", tDAYZONE, 5*HOUR }, /* Eastern Daylight */ + { 0, "cst", tZONE, 6*HOUR }, /* Central Standard */ + { 0, "cdt", tDAYZONE, 6*HOUR }, /* Central Daylight */ + { 0, "mst", tZONE, 7*HOUR }, /* Mountain Standard */ + { 0, "mdt", tDAYZONE, 7*HOUR }, /* Mountain Daylight */ + { 0, "pst", tZONE, 8*HOUR }, /* Pacific Standard */ + { 0, "pdt", tDAYZONE, 8*HOUR }, /* Pacific Daylight */ + { 0, "yst", tZONE, 9*HOUR }, /* Yukon Standard */ + { 0, "ydt", tDAYZONE, 9*HOUR }, /* Yukon Daylight */ + { 0, "hst", tZONE, 10*HOUR }, /* Hawaii Standard */ + { 0, "hdt", tDAYZONE, 10*HOUR }, /* Hawaii Daylight */ + { 0, "cat", tZONE, 10*HOUR }, /* Central Alaska */ + { 0, "ahst", tZONE, 10*HOUR }, /* Alaska-Hawaii Standard */ + { 0, "nt", tZONE, 11*HOUR }, /* Nome */ + { 0, "idlw", tZONE, 12*HOUR }, /* Intl Date Line West */ + { 0, "cet", tZONE, -1*HOUR }, /* Central European */ + { 0, "met", tZONE, -1*HOUR }, /* Middle European */ + { 0, "mewt", tZONE, -1*HOUR }, /* Middle European Winter */ + { 0, "mest", tDAYZONE, -1*HOUR }, /* Middle European Summer */ + { 0, "swt", tZONE, -1*HOUR }, /* Swedish Winter */ + { 0, "sst", tDAYZONE, -1*HOUR }, /* Swedish Summer */ + { 0, "fwt", tZONE, -1*HOUR }, /* French Winter */ + { 0, "fst", tDAYZONE, -1*HOUR }, /* French Summer */ + { 0, "eet", tZONE, -2*HOUR }, /* Eastern Eur, USSR Zone 1 */ + { 0, "bt", tZONE, -3*HOUR }, /* Baghdad, USSR Zone 2 */ + { 0, "it", tZONE, -3*HOUR-30*MINUTE },/* Iran */ + { 0, "zp4", tZONE, -4*HOUR }, /* USSR Zone 3 */ + { 0, "zp5", tZONE, -5*HOUR }, /* USSR Zone 4 */ + { 0, "ist", tZONE, -5*HOUR-30*MINUTE },/* Indian Standard */ + { 0, "zp6", tZONE, -6*HOUR }, /* USSR Zone 5 */ + /* { 0, "nst", tZONE, -6.5*HOUR }, */ /* North Sumatra: Conflict */ + /* { 0, "sst", tZONE, -7*HOUR }, */ /* So Sumatra, USSR 6: Conflict */ + { 0, "wast", tZONE, -7*HOUR }, /* West Australian Standard */ + { 0, "wadt", tDAYZONE, -7*HOUR }, /* West Australian Daylight */ + { 0, "jt", tZONE, -7*HOUR-30*MINUTE },/* Java (3pm in Cronusland!)*/ + { 0, "cct", tZONE, -8*HOUR }, /* China Coast, USSR Zone 7 */ + { 0, "jst", tZONE, -9*HOUR }, /* Japan Std, USSR Zone 8 */ + { 0, "cast", tZONE, -9*HOUR-30*MINUTE },/* Ctrl Australian Std */ + { 0, "cadt", tDAYZONE, -9*HOUR-30*MINUTE },/* Ctrl Australian Daylt */ + { 0, "east", tZONE, -10*HOUR }, /* Eastern Australian Std */ + { 0, "eadt", tDAYZONE, -10*HOUR }, /* Eastern Australian Daylt */ + { 0, "gst", tZONE, -10*HOUR }, /* Guam Std, USSR Zone 9 */ + { 0, "nzt", tZONE, -12*HOUR }, /* New Zealand */ + { 0, "nzst", tZONE, -12*HOUR }, /* New Zealand Standard */ + { 0, "nzdt", tDAYZONE, -12*HOUR }, /* New Zealand Daylight */ + { 0, "idle", tZONE, -12*HOUR }, /* Intl Date Line East */ + + { 0, "dst", tDST, 0 }, + + /* Time units. */ + { 4, "years", tMONTH_UNIT, 12 }, + { 5, "months", tMONTH_UNIT, 1 }, + { 9, "fortnights", tSEC_UNIT, 14 * DAY }, + { 4, "weeks", tSEC_UNIT, 7 * DAY }, + { 3, "days", tSEC_UNIT, DAY }, + { 4, "hours", tSEC_UNIT, HOUR }, + { 3, "minutes", tSEC_UNIT, MINUTE }, + { 3, "seconds", tSEC_UNIT, 1 }, + + /* Relative-time words. */ + { 0, "tomorrow", tSEC_UNIT, DAY }, + { 0, "yesterday", tSEC_UNIT, -DAY }, + { 0, "today", tSEC_UNIT, 0 }, + { 0, "now", tSEC_UNIT, 0 }, + { 0, "last", tUNUMBER, -1 }, + { 0, "this", tSEC_UNIT, 0 }, + { 0, "next", tUNUMBER, 2 }, + { 0, "first", tUNUMBER, 1 }, + { 0, "1st", tUNUMBER, 1 }, +/* { 0, "second", tUNUMBER, 2 }, */ + { 0, "2nd", tUNUMBER, 2 }, + { 0, "third", tUNUMBER, 3 }, + { 0, "3rd", tUNUMBER, 3 }, + { 0, "fourth", tUNUMBER, 4 }, + { 0, "4th", tUNUMBER, 4 }, + { 0, "fifth", tUNUMBER, 5 }, + { 0, "5th", tUNUMBER, 5 }, + { 0, "sixth", tUNUMBER, 6 }, + { 0, "seventh", tUNUMBER, 7 }, + { 0, "eighth", tUNUMBER, 8 }, + { 0, "ninth", tUNUMBER, 9 }, + { 0, "tenth", tUNUMBER, 10 }, + { 0, "eleventh", tUNUMBER, 11 }, + { 0, "twelfth", tUNUMBER, 12 }, + { 0, "ago", tAGO, 1 }, + + /* Military timezones. */ + { 0, "a", tZONE, 1*HOUR }, + { 0, "b", tZONE, 2*HOUR }, + { 0, "c", tZONE, 3*HOUR }, + { 0, "d", tZONE, 4*HOUR }, + { 0, "e", tZONE, 5*HOUR }, + { 0, "f", tZONE, 6*HOUR }, + { 0, "g", tZONE, 7*HOUR }, + { 0, "h", tZONE, 8*HOUR }, + { 0, "i", tZONE, 9*HOUR }, + { 0, "k", tZONE, 10*HOUR }, + { 0, "l", tZONE, 11*HOUR }, + { 0, "m", tZONE, 12*HOUR }, + { 0, "n", tZONE, -1*HOUR }, + { 0, "o", tZONE, -2*HOUR }, + { 0, "p", tZONE, -3*HOUR }, + { 0, "q", tZONE, -4*HOUR }, + { 0, "r", tZONE, -5*HOUR }, + { 0, "s", tZONE, -6*HOUR }, + { 0, "t", tZONE, -7*HOUR }, + { 0, "u", tZONE, -8*HOUR }, + { 0, "v", tZONE, -9*HOUR }, + { 0, "w", tZONE, -10*HOUR }, + { 0, "x", tZONE, -11*HOUR }, + { 0, "y", tZONE, -12*HOUR }, + { 0, "z", tZONE, 0*HOUR }, + + /* End of table. */ + { 0, NULL, 0, 0 } +}; + +/* + * Year is either: + * = A number from 0 to 99, which means a year from 1970 to 2069, or + * = The actual year (>=100). + */ +static time_t +Convert(time_t Month, time_t Day, time_t Year, + time_t Hours, time_t Minutes, time_t Seconds, + time_t Timezone, enum DSTMODE DSTmode) +{ + static int DaysInMonth[12] = { + 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + time_t Julian; + int i; + + if (Year < 69) + Year += 2000; + else if (Year < 100) + Year += 1900; + DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) + ? 29 : 28; + /* Checking for 2038 bogusly assumes that time_t is 32 bits. But + I'm too lazy to try to check for time_t overflow in another way. */ + if (Year < EPOCH || Year > 2038 + || Month < 1 || Month > 12 + /* Lint fluff: "conversion from long may lose accuracy" */ + || Day < 1 || Day > DaysInMonth[(int)--Month] + || Hours < 0 || Hours > 23 + || Minutes < 0 || Minutes > 59 + || Seconds < 0 || Seconds > 59) + return -1; + + Julian = Day - 1; + for (i = 0; i < Month; i++) + Julian += DaysInMonth[i]; + for (i = EPOCH; i < Year; i++) + Julian += 365 + (i % 4 == 0); + Julian *= DAY; + Julian += Timezone; + Julian += Hours * HOUR + Minutes * MINUTE + Seconds; + if (DSTmode == DSTon + || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst)) + Julian -= HOUR; + return Julian; +} + + +static time_t +DSTcorrect(time_t Start, time_t Future) +{ + time_t StartDay; + time_t FutureDay; + + StartDay = (localtime(&Start)->tm_hour + 1) % 24; + FutureDay = (localtime(&Future)->tm_hour + 1) % 24; + return (Future - Start) + (StartDay - FutureDay) * HOUR; +} + + +static time_t +RelativeDate(time_t Start, time_t zone, int dstmode, + time_t DayOrdinal, time_t DayNumber) +{ + struct tm *tm; + time_t t, now; + + t = Start - zone; + tm = gmtime(&t); + now = Start; + now += DAY * ((DayNumber - tm->tm_wday + 7) % 7); + now += 7 * DAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1); + if (dstmode == DSTmaybe) + return DSTcorrect(Start, now); + return now - Start; +} + + +static time_t +RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth) +{ + struct tm *tm; + time_t Month; + time_t Year; + + if (RelMonth == 0) + return 0; + tm = localtime(&Start); + Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth; + Year = Month / 12; + Month = Month % 12 + 1; + return DSTcorrect(Start, + Convert(Month, (time_t)tm->tm_mday, Year, + (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec, + Timezone, DSTmaybe)); +} + +/* + * Tokenizer. + */ +static int +nexttoken(char **in, time_t *value) +{ + char c; + char buff[64]; + + for ( ; ; ) { + while (isspace((unsigned char)**in)) + ++*in; + + /* Skip parenthesized comments. */ + if (**in == '(') { + int Count = 0; + do { + c = *(*in)++; + if (c == '\0') + return c; + if (c == '(') + Count++; + else if (c == ')') + Count--; + } while (Count > 0); + continue; + } + + /* Try the next token in the word table first. */ + /* This allows us to match "2nd", for example. */ + { + char *src = *in; + const struct LEXICON *tp; + unsigned i = 0; + + /* Force to lowercase and strip '.' characters. */ + while (*src != '\0' + && (isalnum((unsigned char)*src) || *src == '.') + && i < sizeof(buff)-1) { + if (*src != '.') { + if (isupper((unsigned char)*src)) + buff[i++] = tolower((unsigned char)*src); + else + buff[i++] = *src; + } + src++; + } + buff[i] = '\0'; + + /* + * Find the first match. If the word can be + * abbreviated, make sure we match at least + * the minimum abbreviation. + */ + for (tp = TimeWords; tp->name; tp++) { + size_t abbrev = tp->abbrev; + if (abbrev == 0) + abbrev = strlen(tp->name); + if (strlen(buff) >= abbrev + && strncmp(tp->name, buff, strlen(buff)) + == 0) { + /* Skip over token. */ + *in = src; + /* Return the match. */ + *value = tp->value; + return tp->type; + } + } + } + + /* + * Not in the word table, maybe it's a number. Note: + * Because '-' and '+' have other special meanings, I + * don't deal with signed numbers here. + */ + if (isdigit((unsigned char)(c = **in))) { + for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); ) + *value = 10 * *value + c - '0'; + (*in)--; + return (tUNUMBER); + } + + return *(*in)++; + } +} + +#define TM_YEAR_ORIGIN 1900 + +/* Yield A - B, measured in seconds. */ +static long +difftm (struct tm *a, struct tm *b) +{ + int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); + int by = b->tm_year + (TM_YEAR_ORIGIN - 1); + int days = ( + /* difference in day of year */ + a->tm_yday - b->tm_yday + /* + intervening leap days */ + + ((ay >> 2) - (by >> 2)) + - (ay/100 - by/100) + + ((ay/100 >> 2) - (by/100 >> 2)) + /* + difference in years * 365 */ + + (long)(ay-by) * 365 + ); + return (days * DAY + (a->tm_hour - b->tm_hour) * HOUR + + (a->tm_min - b->tm_min) * MINUTE + + (a->tm_sec - b->tm_sec)); +} + +/* + * + * The public function. + * + * TODO: tokens[] array should be dynamically sized. + */ +time_t +__archive_get_date(time_t now, char *p) +{ + struct token tokens[256]; + struct gdstate _gds; + struct token *lasttoken; + struct gdstate *gds; + struct tm local, *tm; + struct tm gmt, *gmt_ptr; + time_t Start; + time_t tod; + long tzone; + + /* Clear out the parsed token array. */ + memset(tokens, 0, sizeof(tokens)); + /* Initialize the parser state. */ + memset(&_gds, 0, sizeof(_gds)); + gds = &_gds; + + /* Look up the current time. */ + memset(&local, 0, sizeof(local)); + tm = localtime (&now); + if (tm == NULL) + return -1; + local = *tm; + + /* Look up UTC if we can and use that to determine the current + * timezone offset. */ + memset(&gmt, 0, sizeof(gmt)); + gmt_ptr = gmtime (&now); + if (gmt_ptr != NULL) { + /* Copy, in case localtime and gmtime use the same buffer. */ + gmt = *gmt_ptr; + } + if (gmt_ptr != NULL) + tzone = difftm (&gmt, &local); + else + /* This system doesn't understand timezones; fake it. */ + tzone = 0; + if(local.tm_isdst) + tzone += HOUR; + + /* Tokenize the input string. */ + lasttoken = tokens; + while ((lasttoken->token = nexttoken(&p, &lasttoken->value)) != 0) { + ++lasttoken; + if (lasttoken > tokens + 255) + return -1; + } + gds->tokenp = tokens; + + /* Match phrases until we run out of input tokens. */ + while (gds->tokenp < lasttoken) { + if (!phrase(gds)) + return -1; + } + + /* Use current local timezone if none was specified. */ + if (!gds->HaveZone) { + gds->Timezone = tzone; + gds->DSTmode = DSTmaybe; + } + + /* If a timezone was specified, use that for generating the default + * time components instead of the local timezone. */ + if (gds->HaveZone && gmt_ptr != NULL) { + now -= gds->Timezone; + gmt_ptr = gmtime (&now); + if (gmt_ptr != NULL) + local = *gmt_ptr; + now += gds->Timezone; + } + + if (!gds->HaveYear) + gds->Year = local.tm_year + 1900; + if (!gds->HaveMonth) + gds->Month = local.tm_mon + 1; + if (!gds->HaveDay) + gds->Day = local.tm_mday; + /* Note: No default for hour/min/sec; a specifier that just + * gives date always refers to 00:00 on that date. */ + + /* If we saw more than one time, timezone, weekday, year, month, + * or day, then give up. */ + if (gds->HaveTime > 1 || gds->HaveZone > 1 || gds->HaveWeekDay > 1 + || gds->HaveYear > 1 || gds->HaveMonth > 1 || gds->HaveDay > 1) + return -1; + + /* Compute an absolute time based on whatever absolute information + * we collected. */ + if (gds->HaveYear || gds->HaveMonth || gds->HaveDay + || gds->HaveTime || gds->HaveWeekDay) { + Start = Convert(gds->Month, gds->Day, gds->Year, + gds->Hour, gds->Minutes, gds->Seconds, + gds->Timezone, gds->DSTmode); + if (Start < 0) + return -1; + } else { + Start = now; + if (!gds->HaveRel) + Start -= local.tm_hour * HOUR + local.tm_min * MINUTE + + local.tm_sec; + } + + /* Add the relative offset. */ + Start += gds->RelSeconds; + Start += RelativeMonth(Start, gds->Timezone, gds->RelMonth); + + /* Adjust for day-of-week offsets. */ + if (gds->HaveWeekDay + && !(gds->HaveYear || gds->HaveMonth || gds->HaveDay)) { + tod = RelativeDate(Start, gds->Timezone, + gds->DSTmode, gds->DayOrdinal, gds->DayNumber); + Start += tod; + } + + /* -1 is an error indicator, so return 0 instead of -1 if + * that's the actual time. */ + return Start == -1 ? 0 : Start; +} + + +#if defined(TEST) + +/* ARGSUSED */ +int +main(int argc, char **argv) +{ + time_t d; + + while (*++argv != NULL) { + (void)printf("Input: %s\n", *argv); + d = get_date(*argv); + if (d == -1) + (void)printf("Bad format - couldn't convert.\n"); + else + (void)printf("Output: %s\n", ctime(&d)); + } + exit(0); + /* NOTREACHED */ +} +#endif /* defined(TEST) */ diff --git a/Utilities/cmlibarchive/libarchive/archive_match.c b/Utilities/cmlibarchive/libarchive/archive_match.c new file mode 100644 index 000000000..6b6be9cb2 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_match.c @@ -0,0 +1,1841 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_entry.h" +#include "archive_pathmatch.h" +#include "archive_rb.h" +#include "archive_string.h" + +struct match { + struct match *next; + int matches; + struct archive_mstring pattern; +}; + +struct match_list { + struct match *first; + struct match **last; + int count; + int unmatched_count; + struct match *unmatched_next; + int unmatched_eof; +}; + +struct match_file { + struct archive_rb_node node; + struct match_file *next; + struct archive_mstring pathname; + int flag; + time_t mtime_sec; + long mtime_nsec; + time_t ctime_sec; + long ctime_nsec; +}; + +struct entry_list { + struct match_file *first; + struct match_file **last; + int count; +}; + +struct id_array { + size_t size;/* Allocated size */ + size_t count; + int64_t *ids; +}; + +#define PATTERN_IS_SET 1 +#define TIME_IS_SET 2 +#define ID_IS_SET 4 + +struct archive_match { + struct archive archive; + + /* exclusion/inclusion set flag. */ + int setflag; + + /* + * Matching filename patterns. + */ + struct match_list exclusions; + struct match_list inclusions; + + /* + * Matching time stamps. + */ + time_t now; + int newer_mtime_filter; + time_t newer_mtime_sec; + long newer_mtime_nsec; + int newer_ctime_filter; + time_t newer_ctime_sec; + long newer_ctime_nsec; + int older_mtime_filter; + time_t older_mtime_sec; + long older_mtime_nsec; + int older_ctime_filter; + time_t older_ctime_sec; + long older_ctime_nsec; + /* + * Matching time stamps with its filename. + */ + struct archive_rb_tree exclusion_tree; + struct entry_list exclusion_entry_list; + + /* + * Matching file owners. + */ + struct id_array inclusion_uids; + struct id_array inclusion_gids; + struct match_list inclusion_unames; + struct match_list inclusion_gnames; +}; + +static int add_pattern_from_file(struct archive_match *, + struct match_list *, int, const void *, int); +static int add_entry(struct archive_match *, int, + struct archive_entry *); +static int add_owner_id(struct archive_match *, struct id_array *, + int64_t); +static int add_owner_name(struct archive_match *, struct match_list *, + int, const void *); +static int add_pattern_mbs(struct archive_match *, struct match_list *, + const char *); +static int add_pattern_wcs(struct archive_match *, struct match_list *, + const wchar_t *); +static int cmp_key_mbs(const struct archive_rb_node *, const void *); +static int cmp_key_wcs(const struct archive_rb_node *, const void *); +static int cmp_node_mbs(const struct archive_rb_node *, + const struct archive_rb_node *); +static int cmp_node_wcs(const struct archive_rb_node *, + const struct archive_rb_node *); +static void entry_list_add(struct entry_list *, struct match_file *); +static void entry_list_free(struct entry_list *); +static void entry_list_init(struct entry_list *); +static int error_nomem(struct archive_match *); +static void match_list_add(struct match_list *, struct match *); +static void match_list_free(struct match_list *); +static void match_list_init(struct match_list *); +static int match_list_unmatched_inclusions_next(struct archive_match *, + struct match_list *, int, const void **); +static int match_owner_id(struct id_array *, int64_t); +#if !defined(_WIN32) || defined(__CYGWIN__) +static int match_owner_name_mbs(struct archive_match *, + struct match_list *, const char *); +#else +static int match_owner_name_wcs(struct archive_match *, + struct match_list *, const wchar_t *); +#endif +static int match_path_exclusion(struct archive_match *, + struct match *, int, const void *); +static int match_path_inclusion(struct archive_match *, + struct match *, int, const void *); +static int owner_excluded(struct archive_match *, + struct archive_entry *); +static int path_excluded(struct archive_match *, int, const void *); +static int set_timefilter(struct archive_match *, int, time_t, long, + time_t, long); +static int set_timefilter_pathname_mbs(struct archive_match *, + int, const char *); +static int set_timefilter_pathname_wcs(struct archive_match *, + int, const wchar_t *); +static int set_timefilter_date(struct archive_match *, int, const char *); +static int set_timefilter_date_w(struct archive_match *, int, + const wchar_t *); +static int time_excluded(struct archive_match *, + struct archive_entry *); +static int validate_time_flag(struct archive *, int, const char *); + +time_t __archive_get_date(time_t now, const char *); +#define get_date __archive_get_date + +static const struct archive_rb_tree_ops rb_ops_mbs = { + cmp_node_mbs, cmp_key_mbs +}; + +static const struct archive_rb_tree_ops rb_ops_wcs = { + cmp_node_wcs, cmp_key_wcs +}; + +/* + * The matching logic here needs to be re-thought. I started out to + * try to mimic gtar's matching logic, but it's not entirely + * consistent. In particular 'tar -t' and 'tar -x' interpret patterns + * on the command line as anchored, but --exclude doesn't. + */ + +static int +error_nomem(struct archive_match *a) +{ + archive_set_error(&(a->archive), ENOMEM, "No memory"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} + +/* + * Create an ARCHIVE_MATCH object. + */ +struct archive * +archive_match_new(void) +{ + struct archive_match *a; + + a = (struct archive_match *)calloc(1, sizeof(*a)); + if (a == NULL) + return (NULL); + a->archive.magic = ARCHIVE_MATCH_MAGIC; + a->archive.state = ARCHIVE_STATE_NEW; + match_list_init(&(a->inclusions)); + match_list_init(&(a->exclusions)); + __archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs); + entry_list_init(&(a->exclusion_entry_list)); + match_list_init(&(a->inclusion_unames)); + match_list_init(&(a->inclusion_gnames)); + time(&a->now); + return (&(a->archive)); +} + +/* + * Free an ARCHIVE_MATCH object. + */ +int +archive_match_free(struct archive *_a) +{ + struct archive_match *a; + + if (_a == NULL) + return (ARCHIVE_OK); + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_match_free"); + a = (struct archive_match *)_a; + match_list_free(&(a->inclusions)); + match_list_free(&(a->exclusions)); + entry_list_free(&(a->exclusion_entry_list)); + free(a->inclusion_uids.ids); + free(a->inclusion_gids.ids); + match_list_free(&(a->inclusion_unames)); + match_list_free(&(a->inclusion_gnames)); + free(a); + return (ARCHIVE_OK); +} + +/* + * Convenience function to perform all exclusion tests. + * + * Returns 1 if archive entry is excluded. + * Returns 0 if archive entry is not excluded. + * Returns <0 if something error happened. + */ +int +archive_match_excluded(struct archive *_a, struct archive_entry *entry) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_excluded_ae"); + + a = (struct archive_match *)_a; + if (entry == NULL) { + archive_set_error(&(a->archive), EINVAL, "entry is NULL"); + return (ARCHIVE_FAILED); + } + + r = 0; + if (a->setflag & PATTERN_IS_SET) { +#if defined(_WIN32) && !defined(__CYGWIN__) + r = path_excluded(a, 0, archive_entry_pathname_w(entry)); +#else + r = path_excluded(a, 1, archive_entry_pathname(entry)); +#endif + if (r != 0) + return (r); + } + + if (a->setflag & TIME_IS_SET) { + r = time_excluded(a, entry); + if (r != 0) + return (r); + } + + if (a->setflag & ID_IS_SET) + r = owner_excluded(a, entry); + return (r); +} + +/* + * Utility functions to manage exclusion/inclusion patterns + */ + +int +archive_match_exclude_pattern(struct archive *_a, const char *pattern) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_exclude_pattern"); + a = (struct archive_match *)_a; + + if (pattern == NULL || *pattern == '\0') { + archive_set_error(&(a->archive), EINVAL, "pattern is empty"); + return (ARCHIVE_FAILED); + } + if ((r = add_pattern_mbs(a, &(a->exclusions), pattern)) != ARCHIVE_OK) + return (r); + return (ARCHIVE_OK); +} + +int +archive_match_exclude_pattern_w(struct archive *_a, const wchar_t *pattern) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_w"); + a = (struct archive_match *)_a; + + if (pattern == NULL || *pattern == L'\0') { + archive_set_error(&(a->archive), EINVAL, "pattern is empty"); + return (ARCHIVE_FAILED); + } + if ((r = add_pattern_wcs(a, &(a->exclusions), pattern)) != ARCHIVE_OK) + return (r); + return (ARCHIVE_OK); +} + +int +archive_match_exclude_pattern_from_file(struct archive *_a, + const char *pathname, int nullSeparator) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file"); + a = (struct archive_match *)_a; + + return add_pattern_from_file(a, &(a->exclusions), 1, pathname, + nullSeparator); +} + +int +archive_match_exclude_pattern_from_file_w(struct archive *_a, + const wchar_t *pathname, int nullSeparator) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file_w"); + a = (struct archive_match *)_a; + + return add_pattern_from_file(a, &(a->exclusions), 0, pathname, + nullSeparator); +} + +int +archive_match_include_pattern(struct archive *_a, const char *pattern) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_pattern"); + a = (struct archive_match *)_a; + + if (pattern == NULL || *pattern == '\0') { + archive_set_error(&(a->archive), EINVAL, "pattern is empty"); + return (ARCHIVE_FAILED); + } + if ((r = add_pattern_mbs(a, &(a->inclusions), pattern)) != ARCHIVE_OK) + return (r); + return (ARCHIVE_OK); +} + +int +archive_match_include_pattern_w(struct archive *_a, const wchar_t *pattern) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_pattern_w"); + a = (struct archive_match *)_a; + + if (pattern == NULL || *pattern == L'\0') { + archive_set_error(&(a->archive), EINVAL, "pattern is empty"); + return (ARCHIVE_FAILED); + } + if ((r = add_pattern_wcs(a, &(a->inclusions), pattern)) != ARCHIVE_OK) + return (r); + return (ARCHIVE_OK); +} + +int +archive_match_include_pattern_from_file(struct archive *_a, + const char *pathname, int nullSeparator) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file"); + a = (struct archive_match *)_a; + + return add_pattern_from_file(a, &(a->inclusions), 1, pathname, + nullSeparator); +} + +int +archive_match_include_pattern_from_file_w(struct archive *_a, + const wchar_t *pathname, int nullSeparator) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file_w"); + a = (struct archive_match *)_a; + + return add_pattern_from_file(a, &(a->inclusions), 0, pathname, + nullSeparator); +} + +/* + * Test functions for pathname patterns. + * + * Returns 1 if archive entry is excluded. + * Returns 0 if archive entry is not excluded. + * Returns <0 if something error happened. + */ +int +archive_match_path_excluded(struct archive *_a, + struct archive_entry *entry) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_path_excluded"); + + a = (struct archive_match *)_a; + if (entry == NULL) { + archive_set_error(&(a->archive), EINVAL, "entry is NULL"); + return (ARCHIVE_FAILED); + } + + /* If we don't have exclusion/inclusion pattern set at all, + * the entry is always not excluded. */ + if ((a->setflag & PATTERN_IS_SET) == 0) + return (0); +#if defined(_WIN32) && !defined(__CYGWIN__) + return (path_excluded(a, 0, archive_entry_pathname_w(entry))); +#else + return (path_excluded(a, 1, archive_entry_pathname(entry))); +#endif +} + +/* + * Utilty functions to get statistic information for inclusion patterns. + */ +int +archive_match_path_unmatched_inclusions(struct archive *_a) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions"); + a = (struct archive_match *)_a; + + return (a->inclusions.unmatched_count); +} + +int +archive_match_path_unmatched_inclusions_next(struct archive *_a, + const char **_p) +{ + struct archive_match *a; + const void *v; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next"); + a = (struct archive_match *)_a; + + r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 1, &v); + *_p = (const char *)v; + return (r); +} + +int +archive_match_path_unmatched_inclusions_next_w(struct archive *_a, + const wchar_t **_p) +{ + struct archive_match *a; + const void *v; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next_w"); + a = (struct archive_match *)_a; + + r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 0, &v); + *_p = (const wchar_t *)v; + return (r); +} + +/* + * Add inclusion/exclusion patterns. + */ +static int +add_pattern_mbs(struct archive_match *a, struct match_list *list, + const char *pattern) +{ + struct match *match; + size_t len; + + match = calloc(1, sizeof(*match)); + if (match == NULL) + return (error_nomem(a)); + /* Both "foo/" and "foo" should match "foo/bar". */ + len = strlen(pattern); + if (len && pattern[len - 1] == '/') + --len; + archive_mstring_copy_mbs_len(&(match->pattern), pattern, len); + match_list_add(list, match); + a->setflag |= PATTERN_IS_SET; + return (ARCHIVE_OK); +} + +static int +add_pattern_wcs(struct archive_match *a, struct match_list *list, + const wchar_t *pattern) +{ + struct match *match; + size_t len; + + match = calloc(1, sizeof(*match)); + if (match == NULL) + return (error_nomem(a)); + /* Both "foo/" and "foo" should match "foo/bar". */ + len = wcslen(pattern); + if (len && pattern[len - 1] == L'/') + --len; + archive_mstring_copy_wcs_len(&(match->pattern), pattern, len); + match_list_add(list, match); + a->setflag |= PATTERN_IS_SET; + return (ARCHIVE_OK); +} + +static int +add_pattern_from_file(struct archive_match *a, struct match_list *mlist, + int mbs, const void *pathname, int nullSeparator) +{ + struct archive *ar; + struct archive_entry *ae; + struct archive_string as; + const void *buff; + size_t size; + int64_t offset; + int r; + + ar = archive_read_new(); + if (ar == NULL) { + archive_set_error(&(a->archive), ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + r = archive_read_support_format_raw(ar); + if (r != ARCHIVE_OK) { + archive_copy_error(&(a->archive), ar); + archive_read_free(ar); + return (r); + } + if (mbs) + r = archive_read_open_filename(ar, pathname, 512*20); + else + r = archive_read_open_filename_w(ar, pathname, 512*20); + if (r != ARCHIVE_OK) { + archive_copy_error(&(a->archive), ar); + archive_read_free(ar); + return (r); + } + r = archive_read_next_header(ar, &ae); + if (r != ARCHIVE_OK) { + archive_copy_error(&(a->archive), ar); + archive_read_free(ar); + return (r); + } + + archive_string_init(&as); + + while ((r = archive_read_data_block(ar, &buff, &size, &offset)) + == ARCHIVE_OK) { + const char *b = (const char *)buff; + + while (size) { + const char *s = (const char *)b; + size_t length = 0; + int found_separator = 0; + + while (length < size) { + if (nullSeparator) { + if (*b == '\0') { + found_separator = 1; + break; + } + } else { + if (*b == 0x0d || *b == 0x0a) { + found_separator = 1; + break; + } + } + b++; + length++; + } + if (!found_separator) { + archive_strncat(&as, s, length); + /* Read next data block. */ + break; + } + b++; + size -= length + 1; + archive_strncat(&as, s, length); + + /* If the line is not empty, add the pattern. */ + if (archive_strlen(&as) > 0) { + /* Add pattern. */ + r = add_pattern_mbs(a, mlist, as.s); + if (r != ARCHIVE_OK) { + archive_read_free(ar); + archive_string_free(&as); + return (r); + } + archive_string_empty(&as); + } + } + } + + /* If something error happend, report it immediately. */ + if (r < ARCHIVE_OK) { + archive_copy_error(&(a->archive), ar); + archive_read_free(ar); + archive_string_free(&as); + return (r); + } + + /* If the line is not empty, add the pattern. */ + if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) { + /* Add pattern. */ + r = add_pattern_mbs(a, mlist, as.s); + if (r != ARCHIVE_OK) { + archive_read_free(ar); + archive_string_free(&as); + return (r); + } + } + archive_read_free(ar); + archive_string_free(&as); + return (ARCHIVE_OK); +} + +/* + * Test if pathname is excluded by inclusion/exclusion patterns. + */ +static int +path_excluded(struct archive_match *a, int mbs, const void *pathname) +{ + struct match *match; + struct match *matched; + int r; + + if (a == NULL) + return (0); + + /* Mark off any unmatched inclusions. */ + /* In particular, if a filename does appear in the archive and + * is explicitly included and excluded, then we don't report + * it as missing even though we don't extract it. + */ + matched = NULL; + for (match = a->inclusions.first; match != NULL; + match = match->next){ + if (match->matches == 0 && + (r = match_path_inclusion(a, match, mbs, pathname)) != 0) { + if (r < 0) + return (r); + a->inclusions.unmatched_count--; + match->matches++; + matched = match; + } + } + + /* Exclusions take priority */ + for (match = a->exclusions.first; match != NULL; + match = match->next){ + r = match_path_exclusion(a, match, mbs, pathname); + if (r) + return (r); + } + + /* It's not excluded and we found an inclusion above, so it's + * included. */ + if (matched != NULL) + return (0); + + + /* We didn't find an unmatched inclusion, check the remaining ones. */ + for (match = a->inclusions.first; match != NULL; + match = match->next){ + /* We looked at previously-unmatched inclusions already. */ + if (match->matches > 0 && + (r = match_path_inclusion(a, match, mbs, pathname)) != 0) { + if (r < 0) + return (r); + match->matches++; + return (0); + } + } + + /* If there were inclusions, default is to exclude. */ + if (a->inclusions.first != NULL) + return (1); + + /* No explicit inclusions, default is to match. */ + return (0); +} + +/* + * This is a little odd, but it matches the default behavior of + * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar' + * + */ +static int +match_path_exclusion(struct archive_match *a, struct match *m, + int mbs, const void *pn) +{ + int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END; + int r; + + if (mbs) { + const char *p; + r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p); + if (r == 0) + return (archive_pathmatch(p, (const char *)pn, flag)); + } else { + const wchar_t *p; + r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p); + if (r == 0) + return (archive_pathmatch_w(p, (const wchar_t *)pn, + flag)); + } + if (errno == ENOMEM) + return (error_nomem(a)); + return (0); +} + +/* + * Again, mimic gtar: inclusions are always anchored (have to match + * the beginning of the path) even though exclusions are not anchored. + */ +static int +match_path_inclusion(struct archive_match *a, struct match *m, + int mbs, const void *pn) +{ + int flag = PATHMATCH_NO_ANCHOR_END; + int r; + + if (mbs) { + const char *p; + r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p); + if (r == 0) + return (archive_pathmatch(p, (const char *)pn, flag)); + } else { + const wchar_t *p; + r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p); + if (r == 0) + return (archive_pathmatch_w(p, (const wchar_t *)pn, + flag)); + } + if (errno == ENOMEM) + return (error_nomem(a)); + return (0); +} + +static void +match_list_init(struct match_list *list) +{ + list->first = NULL; + list->last = &(list->first); + list->count = 0; +} + +static void +match_list_free(struct match_list *list) +{ + struct match *p, *q; + + for (p = list->first; p != NULL; ) { + q = p; + p = p->next; + archive_mstring_clean(&(q->pattern)); + free(q); + } +} + +static void +match_list_add(struct match_list *list, struct match *m) +{ + *list->last = m; + list->last = &(m->next); + list->count++; + list->unmatched_count++; +} + +static int +match_list_unmatched_inclusions_next(struct archive_match *a, + struct match_list *list, int mbs, const void **vp) +{ + struct match *m; + + *vp = NULL; + if (list->unmatched_eof) { + list->unmatched_eof = 0; + return (ARCHIVE_EOF); + } + if (list->unmatched_next == NULL) { + if (list->unmatched_count == 0) + return (ARCHIVE_EOF); + list->unmatched_next = list->first; + } + + for (m = list->unmatched_next; m != NULL; m = m->next) { + int r; + + if (m->matches) + continue; + if (mbs) { + const char *p; + r = archive_mstring_get_mbs(&(a->archive), + &(m->pattern), &p); + if (r < 0 && errno == ENOMEM) + return (error_nomem(a)); + if (p == NULL) + p = ""; + *vp = p; + } else { + const wchar_t *p; + r = archive_mstring_get_wcs(&(a->archive), + &(m->pattern), &p); + if (r < 0 && errno == ENOMEM) + return (error_nomem(a)); + if (p == NULL) + p = L""; + *vp = p; + } + list->unmatched_next = m->next; + if (list->unmatched_next == NULL) + /* To return EOF next time. */ + list->unmatched_eof = 1; + return (ARCHIVE_OK); + } + list->unmatched_next = NULL; + return (ARCHIVE_EOF); +} + +/* + * Utility functions to manage inclusion timestamps. + */ +int +archive_match_include_time(struct archive *_a, int flag, time_t sec, + long nsec) +{ + int r; + + r = validate_time_flag(_a, flag, "archive_match_include_time"); + if (r != ARCHIVE_OK) + return (r); + return set_timefilter((struct archive_match *)_a, flag, + sec, nsec, sec, nsec); +} + +int +archive_match_include_date(struct archive *_a, int flag, + const char *datestr) +{ + int r; + + r = validate_time_flag(_a, flag, "archive_match_include_date"); + if (r != ARCHIVE_OK) + return (r); + return set_timefilter_date((struct archive_match *)_a, flag, datestr); +} + +int +archive_match_include_date_w(struct archive *_a, int flag, + const wchar_t *datestr) +{ + int r; + + r = validate_time_flag(_a, flag, "archive_match_include_date_w"); + if (r != ARCHIVE_OK) + return (r); + + return set_timefilter_date_w((struct archive_match *)_a, flag, datestr); +} + +int +archive_match_include_file_time(struct archive *_a, int flag, + const char *pathname) +{ + int r; + + r = validate_time_flag(_a, flag, "archive_match_include_file_time"); + if (r != ARCHIVE_OK) + return (r); + return set_timefilter_pathname_mbs((struct archive_match *)_a, + flag, pathname); +} + +int +archive_match_include_file_time_w(struct archive *_a, int flag, + const wchar_t *pathname) +{ + int r; + + r = validate_time_flag(_a, flag, "archive_match_include_file_time_w"); + if (r != ARCHIVE_OK) + return (r); + return set_timefilter_pathname_wcs((struct archive_match *)_a, + flag, pathname); +} + +int +archive_match_exclude_entry(struct archive *_a, int flag, + struct archive_entry *entry) +{ + struct archive_match *a; + int r; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_time_include_entry"); + a = (struct archive_match *)_a; + + if (entry == NULL) { + archive_set_error(&(a->archive), EINVAL, "entry is NULL"); + return (ARCHIVE_FAILED); + } + r = validate_time_flag(_a, flag, "archive_match_exclude_entry"); + if (r != ARCHIVE_OK) + return (r); + return (add_entry(a, flag, entry)); +} + +/* + * Test function for time stamps. + * + * Returns 1 if archive entry is excluded. + * Returns 0 if archive entry is not excluded. + * Returns <0 if something error happened. + */ +int +archive_match_time_excluded(struct archive *_a, + struct archive_entry *entry) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_time_excluded_ae"); + + a = (struct archive_match *)_a; + if (entry == NULL) { + archive_set_error(&(a->archive), EINVAL, "entry is NULL"); + return (ARCHIVE_FAILED); + } + + /* If we don't have inclusion time set at all, the entry is always + * not excluded. */ + if ((a->setflag & TIME_IS_SET) == 0) + return (0); + return (time_excluded(a, entry)); +} + +static int +validate_time_flag(struct archive *_a, int flag, const char *_fn) +{ + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, _fn); + + /* Check a type of time. */ + if (flag & + ((~(ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) & 0xff00)) { + archive_set_error(_a, EINVAL, "Invalid time flag"); + return (ARCHIVE_FAILED); + } + if ((flag & (ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) == 0) { + archive_set_error(_a, EINVAL, "No time flag"); + return (ARCHIVE_FAILED); + } + + /* Check a type of comparison. */ + if (flag & + ((~(ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER + | ARCHIVE_MATCH_EQUAL)) & 0x00ff)) { + archive_set_error(_a, EINVAL, "Invalid comparison flag"); + return (ARCHIVE_FAILED); + } + if ((flag & (ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER + | ARCHIVE_MATCH_EQUAL)) == 0) { + archive_set_error(_a, EINVAL, "No comparison flag"); + return (ARCHIVE_FAILED); + } + + return (ARCHIVE_OK); +} + +#define JUST_EQUAL(t) (((t) & (ARCHIVE_MATCH_EQUAL |\ + ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER)) == ARCHIVE_MATCH_EQUAL) +static int +set_timefilter(struct archive_match *a, int timetype, + time_t mtime_sec, long mtime_nsec, time_t ctime_sec, long ctime_nsec) +{ + if (timetype & ARCHIVE_MATCH_MTIME) { + if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) { + a->newer_mtime_filter = timetype; + a->newer_mtime_sec = mtime_sec; + a->newer_mtime_nsec = mtime_nsec; + a->setflag |= TIME_IS_SET; + } + if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) { + a->older_mtime_filter = timetype; + a->older_mtime_sec = mtime_sec; + a->older_mtime_nsec = mtime_nsec; + a->setflag |= TIME_IS_SET; + } + } + if (timetype & ARCHIVE_MATCH_CTIME) { + if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) { + a->newer_ctime_filter = timetype; + a->newer_ctime_sec = ctime_sec; + a->newer_ctime_nsec = ctime_nsec; + a->setflag |= TIME_IS_SET; + } + if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) { + a->older_ctime_filter = timetype; + a->older_ctime_sec = ctime_sec; + a->older_ctime_nsec = ctime_nsec; + a->setflag |= TIME_IS_SET; + } + } + return (ARCHIVE_OK); +} + +static int +set_timefilter_date(struct archive_match *a, int timetype, const char *datestr) +{ + time_t t; + + if (datestr == NULL || *datestr == '\0') { + archive_set_error(&(a->archive), EINVAL, "date is empty"); + return (ARCHIVE_FAILED); + } + t = get_date(a->now, datestr); + if (t == (time_t)-1) { + archive_set_error(&(a->archive), EINVAL, "invalid date string"); + return (ARCHIVE_FAILED); + } + return set_timefilter(a, timetype, t, 0, t, 0); +} + +static int +set_timefilter_date_w(struct archive_match *a, int timetype, + const wchar_t *datestr) +{ + struct archive_string as; + time_t t; + + if (datestr == NULL || *datestr == L'\0') { + archive_set_error(&(a->archive), EINVAL, "date is empty"); + return (ARCHIVE_FAILED); + } + + archive_string_init(&as); + if (archive_string_append_from_wcs(&as, datestr, wcslen(datestr)) < 0) { + archive_string_free(&as); + if (errno == ENOMEM) + return (error_nomem(a)); + archive_set_error(&(a->archive), -1, + "Failed to convert WCS to MBS"); + return (ARCHIVE_FAILED); + } + t = get_date(a->now, as.s); + archive_string_free(&as); + if (t == (time_t)-1) { + archive_set_error(&(a->archive), EINVAL, "invalid date string"); + return (ARCHIVE_FAILED); + } + return set_timefilter(a, timetype, t, 0, t, 0); +} + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) +static int +set_timefilter_find_data(struct archive_match *a, int timetype, + DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime, + DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime) +{ + ULARGE_INTEGER utc; + time_t ctime_sec, mtime_sec; + long ctime_ns, mtime_ns; + + utc.HighPart = ftCreationTime_dwHighDateTime; + utc.LowPart = ftCreationTime_dwLowDateTime; + if (utc.QuadPart >= EPOC_TIME) { + utc.QuadPart -= EPOC_TIME; + ctime_sec = (time_t)(utc.QuadPart / 10000000); + ctime_ns = (long)(utc.QuadPart % 10000000) * 100; + } else { + ctime_sec = 0; + ctime_ns = 0; + } + utc.HighPart = ftLastWriteTime_dwHighDateTime; + utc.LowPart = ftLastWriteTime_dwLowDateTime; + if (utc.QuadPart >= EPOC_TIME) { + utc.QuadPart -= EPOC_TIME; + mtime_sec = (time_t)(utc.QuadPart / 10000000); + mtime_ns = (long)(utc.QuadPart % 10000000) * 100; + } else { + mtime_sec = 0; + mtime_ns = 0; + } + return set_timefilter(a, timetype, + mtime_sec, mtime_ns, ctime_sec, ctime_ns); +} + +static int +set_timefilter_pathname_mbs(struct archive_match *a, int timetype, + const char *path) +{ + /* NOTE: stat() on Windows cannot handle nano seconds. */ + HANDLE h; + WIN32_FIND_DATA d; + + if (path == NULL || *path == '\0') { + archive_set_error(&(a->archive), EINVAL, "pathname is empty"); + return (ARCHIVE_FAILED); + } + h = FindFirstFileA(path, &d); + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + archive_set_error(&(a->archive), errno, + "Failed to FindFirstFileA"); + return (ARCHIVE_FAILED); + } + FindClose(h); + return set_timefilter_find_data(a, timetype, + d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime, + d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime); +} + +static int +set_timefilter_pathname_wcs(struct archive_match *a, int timetype, + const wchar_t *path) +{ + HANDLE h; + WIN32_FIND_DATAW d; + + if (path == NULL || *path == L'\0') { + archive_set_error(&(a->archive), EINVAL, "pathname is empty"); + return (ARCHIVE_FAILED); + } + h = FindFirstFileW(path, &d); + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + archive_set_error(&(a->archive), errno, + "Failed to FindFirstFile"); + return (ARCHIVE_FAILED); + } + FindClose(h); + return set_timefilter_find_data(a, timetype, + d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime, + d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime); +} + +#else /* _WIN32 && !__CYGWIN__ */ + +static int +set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st) +{ + struct archive_entry *ae; + time_t ctime_sec, mtime_sec; + long ctime_ns, mtime_ns; + + ae = archive_entry_new(); + if (ae == NULL) + return (error_nomem(a)); + archive_entry_copy_stat(ae, st); + ctime_sec = archive_entry_ctime(ae); + ctime_ns = archive_entry_ctime_nsec(ae); + mtime_sec = archive_entry_mtime(ae); + mtime_ns = archive_entry_mtime_nsec(ae); + archive_entry_free(ae); + return set_timefilter(a, timetype, mtime_sec, mtime_ns, + ctime_sec, ctime_ns); +} + +static int +set_timefilter_pathname_mbs(struct archive_match *a, int timetype, + const char *path) +{ + struct stat st; + + if (path == NULL || *path == '\0') { + archive_set_error(&(a->archive), EINVAL, "pathname is empty"); + return (ARCHIVE_FAILED); + } + if (stat(path, &st) != 0) { + archive_set_error(&(a->archive), errno, "Failed to stat()"); + return (ARCHIVE_FAILED); + } + return (set_timefilter_stat(a, timetype, &st)); +} + +static int +set_timefilter_pathname_wcs(struct archive_match *a, int timetype, + const wchar_t *path) +{ + struct archive_string as; + int r; + + if (path == NULL || *path == L'\0') { + archive_set_error(&(a->archive), EINVAL, "pathname is empty"); + return (ARCHIVE_FAILED); + } + + /* Convert WCS filename to MBS filename. */ + archive_string_init(&as); + if (archive_string_append_from_wcs(&as, path, wcslen(path)) < 0) { + archive_string_free(&as); + if (errno == ENOMEM) + return (error_nomem(a)); + archive_set_error(&(a->archive), -1, + "Failed to convert WCS to MBS"); + return (ARCHIVE_FAILED); + } + + r = set_timefilter_pathname_mbs(a, timetype, as.s); + archive_string_free(&as); + + return (r); +} +#endif /* _WIN32 && !__CYGWIN__ */ + +/* + * Call back funtions for archive_rb. + */ +static int +cmp_node_mbs(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + struct match_file *f1 = (struct match_file *)(uintptr_t)n1; + struct match_file *f2 = (struct match_file *)(uintptr_t)n2; + const char *p1, *p2; + + archive_mstring_get_mbs(NULL, &(f1->pathname), &p1); + archive_mstring_get_mbs(NULL, &(f2->pathname), &p2); + if (p1 == NULL) + return (1); + if (p2 == NULL) + return (-1); + return (strcmp(p1, p2)); +} + +static int +cmp_key_mbs(const struct archive_rb_node *n, const void *key) +{ + struct match_file *f = (struct match_file *)(uintptr_t)n; + const char *p; + + archive_mstring_get_mbs(NULL, &(f->pathname), &p); + if (p == NULL) + return (-1); + return (strcmp(p, (const char *)key)); +} + +static int +cmp_node_wcs(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + struct match_file *f1 = (struct match_file *)(uintptr_t)n1; + struct match_file *f2 = (struct match_file *)(uintptr_t)n2; + const wchar_t *p1, *p2; + + archive_mstring_get_wcs(NULL, &(f1->pathname), &p1); + archive_mstring_get_wcs(NULL, &(f2->pathname), &p2); + if (p1 == NULL) + return (1); + if (p2 == NULL) + return (-1); + return (wcscmp(p1, p2)); +} + +static int +cmp_key_wcs(const struct archive_rb_node *n, const void *key) +{ + struct match_file *f = (struct match_file *)(uintptr_t)n; + const wchar_t *p; + + archive_mstring_get_wcs(NULL, &(f->pathname), &p); + if (p == NULL) + return (-1); + return (wcscmp(p, (const wchar_t *)key)); +} + +static void +entry_list_init(struct entry_list *list) +{ + list->first = NULL; + list->last = &(list->first); + list->count = 0; +} + +static void +entry_list_free(struct entry_list *list) +{ + struct match_file *p, *q; + + for (p = list->first; p != NULL; ) { + q = p; + p = p->next; + archive_mstring_clean(&(q->pathname)); + free(q); + } +} + +static void +entry_list_add(struct entry_list *list, struct match_file *file) +{ + *list->last = file; + list->last = &(file->next); + list->count++; +} + +static int +add_entry(struct archive_match *a, int flag, + struct archive_entry *entry) +{ + struct match_file *f; + const void *pathname; + int r; + + f = calloc(1, sizeof(*f)); + if (f == NULL) + return (error_nomem(a)); + +#if defined(_WIN32) && !defined(__CYGWIN__) + pathname = archive_entry_pathname_w(entry); + if (pathname == NULL) { + free(f); + archive_set_error(&(a->archive), EINVAL, "pathname is NULL"); + return (ARCHIVE_FAILED); + } + archive_mstring_copy_wcs(&(f->pathname), pathname); + a->exclusion_tree.rbt_ops = &rb_ops_wcs; +#else + (void)rb_ops_wcs; + pathname = archive_entry_pathname(entry); + if (pathname == NULL) { + free(f); + archive_set_error(&(a->archive), EINVAL, "pathname is NULL"); + return (ARCHIVE_FAILED); + } + archive_mstring_copy_mbs(&(f->pathname), pathname); + a->exclusion_tree.rbt_ops = &rb_ops_mbs; +#endif + f->flag = flag; + f->mtime_sec = archive_entry_mtime(entry); + f->mtime_nsec = archive_entry_mtime_nsec(entry); + f->ctime_sec = archive_entry_ctime(entry); + f->ctime_nsec = archive_entry_ctime_nsec(entry); + r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node)); + if (!r) { + struct match_file *f2; + + /* Get the duplicated file. */ + f2 = (struct match_file *)__archive_rb_tree_find_node( + &(a->exclusion_tree), pathname); + + /* + * We always overwrite comparison condision. + * If you do not want to overwrite it, you should not + * call archive_match_exclude_entry(). We cannot know + * what behavior you really expect since overwriting + * condition might be different with the flag. + */ + if (f2 != NULL) { + f2->flag = f->flag; + f2->mtime_sec = f->mtime_sec; + f2->mtime_nsec = f->mtime_nsec; + f2->ctime_sec = f->ctime_sec; + f2->ctime_nsec = f->ctime_nsec; + } + /* Release the duplicated file. */ + archive_mstring_clean(&(f->pathname)); + free(f); + return (ARCHIVE_OK); + } + entry_list_add(&(a->exclusion_entry_list), f); + a->setflag |= TIME_IS_SET; + return (ARCHIVE_OK); +} + +/* + * Test if entry is excluded by its timestamp. + */ +static int +time_excluded(struct archive_match *a, struct archive_entry *entry) +{ + struct match_file *f; + const void *pathname; + time_t sec; + long nsec; + + /* + * If this file/dir is excluded by a time comparison, skip it. + */ + if (a->newer_ctime_filter) { + /* If ctime is not set, use mtime instead. */ + if (archive_entry_ctime_is_set(entry)) + sec = archive_entry_ctime(entry); + else + sec = archive_entry_mtime(entry); + if (sec < a->newer_ctime_sec) + return (1); /* Too old, skip it. */ + if (sec == a->newer_ctime_sec) { + if (archive_entry_ctime_is_set(entry)) + nsec = archive_entry_ctime_nsec(entry); + else + nsec = archive_entry_mtime_nsec(entry); + if (nsec < a->newer_ctime_nsec) + return (1); /* Too old, skip it. */ + if (nsec == a->newer_ctime_nsec && + (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL) + == 0) + return (1); /* Equal, skip it. */ + } + } + if (a->older_ctime_filter) { + /* If ctime is not set, use mtime instead. */ + if (archive_entry_ctime_is_set(entry)) + sec = archive_entry_ctime(entry); + else + sec = archive_entry_mtime(entry); + if (sec > a->older_ctime_sec) + return (1); /* Too new, skip it. */ + if (sec == a->older_ctime_sec) { + if (archive_entry_ctime_is_set(entry)) + nsec = archive_entry_ctime_nsec(entry); + else + nsec = archive_entry_mtime_nsec(entry); + if (nsec > a->older_ctime_nsec) + return (1); /* Too new, skip it. */ + if (nsec == a->older_ctime_nsec && + (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL) + == 0) + return (1); /* Eeual, skip it. */ + } + } + if (a->newer_mtime_filter) { + sec = archive_entry_mtime(entry); + if (sec < a->newer_mtime_sec) + return (1); /* Too old, skip it. */ + if (sec == a->newer_mtime_sec) { + nsec = archive_entry_mtime_nsec(entry); + if (nsec < a->newer_mtime_nsec) + return (1); /* Too old, skip it. */ + if (nsec == a->newer_mtime_nsec && + (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL) + == 0) + return (1); /* Equal, skip it. */ + } + } + if (a->older_mtime_filter) { + sec = archive_entry_mtime(entry); + if (sec > a->older_mtime_sec) + return (1); /* Too new, skip it. */ + nsec = archive_entry_mtime_nsec(entry); + if (sec == a->older_mtime_sec) { + if (nsec > a->older_mtime_nsec) + return (1); /* Too new, skip it. */ + if (nsec == a->older_mtime_nsec && + (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL) + == 0) + return (1); /* Equal, skip it. */ + } + } + + /* If there is no excluson list, include the file. */ + if (a->exclusion_entry_list.count == 0) + return (0); + +#if defined(_WIN32) && !defined(__CYGWIN__) + pathname = archive_entry_pathname_w(entry); + a->exclusion_tree.rbt_ops = &rb_ops_wcs; +#else + (void)rb_ops_wcs; + pathname = archive_entry_pathname(entry); + a->exclusion_tree.rbt_ops = &rb_ops_mbs; +#endif + if (pathname == NULL) + return (0); + + f = (struct match_file *)__archive_rb_tree_find_node( + &(a->exclusion_tree), pathname); + /* If the file wasn't rejected, include it. */ + if (f == NULL) + return (0); + + if (f->flag & ARCHIVE_MATCH_CTIME) { + sec = archive_entry_ctime(entry); + if (f->ctime_sec > sec) { + if (f->flag & ARCHIVE_MATCH_OLDER) + return (1); + } else if (f->ctime_sec < sec) { + if (f->flag & ARCHIVE_MATCH_NEWER) + return (1); + } else { + nsec = archive_entry_ctime_nsec(entry); + if (f->ctime_nsec > nsec) { + if (f->flag & ARCHIVE_MATCH_OLDER) + return (1); + } else if (f->ctime_nsec < nsec) { + if (f->flag & ARCHIVE_MATCH_NEWER) + return (1); + } else if (f->flag & ARCHIVE_MATCH_EQUAL) + return (1); + } + } + if (f->flag & ARCHIVE_MATCH_MTIME) { + sec = archive_entry_mtime(entry); + if (f->mtime_sec > sec) { + if (f->flag & ARCHIVE_MATCH_OLDER) + return (1); + } else if (f->mtime_sec < sec) { + if (f->flag & ARCHIVE_MATCH_NEWER) + return (1); + } else { + nsec = archive_entry_mtime_nsec(entry); + if (f->mtime_nsec > nsec) { + if (f->flag & ARCHIVE_MATCH_OLDER) + return (1); + } else if (f->mtime_nsec < nsec) { + if (f->flag & ARCHIVE_MATCH_NEWER) + return (1); + } else if (f->flag & ARCHIVE_MATCH_EQUAL) + return (1); + } + } + return (0); +} + +/* + * Utility functions to manage inclusion owners + */ + +int +archive_match_include_uid(struct archive *_a, int64_t uid) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_uid"); + a = (struct archive_match *)_a; + return (add_owner_id(a, &(a->inclusion_uids), uid)); +} + +int +archive_match_include_gid(struct archive *_a, int64_t gid) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_gid"); + a = (struct archive_match *)_a; + return (add_owner_id(a, &(a->inclusion_gids), gid)); +} + +int +archive_match_include_uname(struct archive *_a, const char *uname) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_uname"); + a = (struct archive_match *)_a; + return (add_owner_name(a, &(a->inclusion_unames), 1, uname)); +} + +int +archive_match_include_uname_w(struct archive *_a, const wchar_t *uname) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_uname_w"); + a = (struct archive_match *)_a; + return (add_owner_name(a, &(a->inclusion_unames), 0, uname)); +} + +int +archive_match_include_gname(struct archive *_a, const char *gname) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_gname"); + a = (struct archive_match *)_a; + return (add_owner_name(a, &(a->inclusion_gnames), 1, gname)); +} + +int +archive_match_include_gname_w(struct archive *_a, const wchar_t *gname) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_include_gname_w"); + a = (struct archive_match *)_a; + return (add_owner_name(a, &(a->inclusion_gnames), 0, gname)); +} + +/* + * Test function for owner(uid, gid, uname, gname). + * + * Returns 1 if archive entry is excluded. + * Returns 0 if archive entry is not excluded. + * Returns <0 if something error happened. + */ +int +archive_match_owner_excluded(struct archive *_a, + struct archive_entry *entry) +{ + struct archive_match *a; + + archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, + ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae"); + + a = (struct archive_match *)_a; + if (entry == NULL) { + archive_set_error(&(a->archive), EINVAL, "entry is NULL"); + return (ARCHIVE_FAILED); + } + + /* If we don't have inclusion id set at all, the entry is always + * not excluded. */ + if ((a->setflag & ID_IS_SET) == 0) + return (0); + return (owner_excluded(a, entry)); +} + +static int +add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id) +{ + unsigned i; + + if (ids->count + 1 >= ids->size) { + void *p; + + if (ids->size == 0) + ids->size = 8; + else + ids->size *= 2; + p = realloc(ids->ids, sizeof(*ids->ids) * ids->size); + if (p == NULL) + return (error_nomem(a)); + ids->ids = (int64_t *)p; + } + + /* Find an insert point. */ + for (i = 0; i < ids->count; i++) { + if (ids->ids[i] >= id) + break; + } + + /* Add oowner id. */ + if (i == ids->count) + ids->ids[ids->count++] = id; + else if (ids->ids[i] != id) { + memmove(&(ids->ids[i+1]), &(ids->ids[i]), + (ids->count - i) * sizeof(ids->ids[0])); + ids->ids[i] = id; + ids->count++; + } + a->setflag |= ID_IS_SET; + return (ARCHIVE_OK); +} + +static int +match_owner_id(struct id_array *ids, int64_t id) +{ + unsigned b, m, t; + + t = 0; + b = (unsigned)ids->count; + while (t < b) { + m = (t + b)>>1; + if (ids->ids[m] == id) + return (1); + if (ids->ids[m] < id) + t = m + 1; + else + b = m; + } + return (0); +} + +static int +add_owner_name(struct archive_match *a, struct match_list *list, + int mbs, const void *name) +{ + struct match *match; + + match = calloc(1, sizeof(*match)); + if (match == NULL) + return (error_nomem(a)); + if (mbs) + archive_mstring_copy_mbs(&(match->pattern), name); + else + archive_mstring_copy_wcs(&(match->pattern), name); + match_list_add(list, match); + a->setflag |= ID_IS_SET; + return (ARCHIVE_OK); +} + +#if !defined(_WIN32) || defined(__CYGWIN__) +static int +match_owner_name_mbs(struct archive_match *a, struct match_list *list, + const char *name) +{ + struct match *m; + const char *p; + + if (name == NULL || *name == '\0') + return (0); + for (m = list->first; m; m = m->next) { + if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p) + < 0 && errno == ENOMEM) + return (error_nomem(a)); + if (p != NULL && strcmp(p, name) == 0) { + m->matches++; + return (1); + } + } + return (0); +} +#else +static int +match_owner_name_wcs(struct archive_match *a, struct match_list *list, + const wchar_t *name) +{ + struct match *m; + const wchar_t *p; + + if (name == NULL || *name == L'\0') + return (0); + for (m = list->first; m; m = m->next) { + if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p) + < 0 && errno == ENOMEM) + return (error_nomem(a)); + if (p != NULL && wcscmp(p, name) == 0) { + m->matches++; + return (1); + } + } + return (0); +} +#endif + +/* + * Test if entry is excluded by uid, gid, uname or gname. + */ +static int +owner_excluded(struct archive_match *a, struct archive_entry *entry) +{ + int r; + + if (a->inclusion_uids.count) { + if (!match_owner_id(&(a->inclusion_uids), + archive_entry_uid(entry))) + return (1); + } + + if (a->inclusion_gids.count) { + if (!match_owner_id(&(a->inclusion_gids), + archive_entry_gid(entry))) + return (1); + } + + if (a->inclusion_unames.count) { +#if defined(_WIN32) && !defined(__CYGWIN__) + r = match_owner_name_wcs(a, &(a->inclusion_unames), + archive_entry_uname_w(entry)); +#else + r = match_owner_name_mbs(a, &(a->inclusion_unames), + archive_entry_uname(entry)); +#endif + if (!r) + return (1); + else if (r < 0) + return (r); + } + + if (a->inclusion_gnames.count) { +#if defined(_WIN32) && !defined(__CYGWIN__) + r = match_owner_name_wcs(a, &(a->inclusion_gnames), + archive_entry_gname_w(entry)); +#else + r = match_owner_name_mbs(a, &(a->inclusion_gnames), + archive_entry_gname(entry)); +#endif + if (!r) + return (1); + else if (r < 0) + return (r); + } + return (0); +} + diff --git a/Utilities/cmlibarchive/libarchive/archive_options.c b/Utilities/cmlibarchive/libarchive/archive_options.c index 79b4ffbda..220ebd417 100644 --- a/Utilities/cmlibarchive/libarchive/archive_options.c +++ b/Utilities/cmlibarchive/libarchive/archive_options.c @@ -38,6 +38,7 @@ _archive_set_option(struct archive *a, int magic, const char *fn, option_handler use_option) { const char *mp, *op, *vp; + int r; archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); @@ -47,10 +48,24 @@ _archive_set_option(struct archive *a, if (op == NULL && vp == NULL) return (ARCHIVE_OK); - if (op == NULL) + if (op == NULL) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option"); return (ARCHIVE_FAILED); + } - return use_option(a, mp, op, vp); + r = use_option(a, mp, op, vp); + if (r == ARCHIVE_WARN - 1) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unknown module name: `%s'", mp); + return (ARCHIVE_FAILED); + } + if (r == ARCHIVE_WARN) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Undefined option: `%s%s%s%s%s%s'", + vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:""); + return (ARCHIVE_FAILED); + } + return (r); } int @@ -72,6 +87,8 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons if (r2 == ARCHIVE_FATAL) return (ARCHIVE_FATAL); + if (r2 == ARCHIVE_WARN - 1) + return r1; return r1 > r2 ? r1 : r2; } @@ -79,7 +96,7 @@ int _archive_set_options(struct archive *a, const char *options, int magic, const char *fn, option_handler use_option) { - int allok = 1, anyok = 0, r; + int allok = 1, anyok = 0, ignore_mod_err = 0, r; char *data; const char *s, *mod, *opt, *val; @@ -96,12 +113,42 @@ _archive_set_options(struct archive *a, const char *options, mod = opt = val = NULL; parse_option(&s, &mod, &opt, &val); + if (mod == NULL && opt != NULL && + strcmp("__ignore_wrong_module_name__", opt) == 0) { + /* Ignore module name error */ + if (val != NULL) { + ignore_mod_err = 1; + anyok = 1; + } + continue; + } r = use_option(a, mod, opt, val); if (r == ARCHIVE_FATAL) { free(data); return (ARCHIVE_FATAL); } + if (r == ARCHIVE_FAILED && mod != NULL) { + free(data); + return (ARCHIVE_FAILED); + } + if (r == ARCHIVE_WARN - 1) { + if (ignore_mod_err) + continue; + /* The module name is wrong. */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unknown module name: `%s'", mod); + free(data); + return (ARCHIVE_FAILED); + } + if (r == ARCHIVE_WARN) { + /* The option name is wrong. No-one used this. */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Undefined option: `%s%s%s'", + mod?mod:"", mod?":":"", opt); + free(data); + return (ARCHIVE_FAILED); + } if (r == ARCHIVE_OK) anyok = 1; else diff --git a/Utilities/cmlibarchive/libarchive/archive_pathmatch.c b/Utilities/cmlibarchive/libarchive/archive_pathmatch.c new file mode 100644 index 000000000..505252a18 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_pathmatch.c @@ -0,0 +1,459 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_WCHAR_H +#include <wchar.h> +#endif + +#include "archive_pathmatch.h" + +/* + * Check whether a character 'c' is matched by a list specification [...]: + * * Leading '!' or '^' negates the class. + * * <char>-<char> is a range of characters + * * \<char> removes any special meaning for <char> + * + * Some interesting boundary cases: + * a-d-e is one range (a-d) followed by two single characters - and e. + * \a-\d is same as a-d + * a\-d is three single characters: a, d, - + * Trailing - is not special (so [a-] is two characters a and -). + * Initial - is not special ([a-] is same as [-a] is same as [\\-a]) + * This function never sees a trailing \. + * [] always fails + * [!] always succeeds + */ +static int +pm_list(const char *start, const char *end, const char c, int flags) +{ + const char *p = start; + char rangeStart = '\0', nextRangeStart; + int match = 1, nomatch = 0; + + /* This will be used soon... */ + (void)flags; /* UNUSED */ + + /* If this is a negated class, return success for nomatch. */ + if ((*p == '!' || *p == '^') && p < end) { + match = 0; + nomatch = 1; + ++p; + } + + while (p < end) { + nextRangeStart = '\0'; + switch (*p) { + case '-': + /* Trailing or initial '-' is not special. */ + if ((rangeStart == '\0') || (p == end - 1)) { + if (*p == c) + return (match); + } else { + char rangeEnd = *++p; + if (rangeEnd == '\\') + rangeEnd = *++p; + if ((rangeStart <= c) && (c <= rangeEnd)) + return (match); + } + break; + case '\\': + ++p; + /* Fall through */ + default: + if (*p == c) + return (match); + nextRangeStart = *p; /* Possible start of range. */ + } + rangeStart = nextRangeStart; + ++p; + } + return (nomatch); +} + +static int +pm_list_w(const wchar_t *start, const wchar_t *end, const wchar_t c, int flags) +{ + const wchar_t *p = start; + wchar_t rangeStart = L'\0', nextRangeStart; + int match = 1, nomatch = 0; + + /* This will be used soon... */ + (void)flags; /* UNUSED */ + + /* If this is a negated class, return success for nomatch. */ + if ((*p == L'!' || *p == L'^') && p < end) { + match = 0; + nomatch = 1; + ++p; + } + + while (p < end) { + nextRangeStart = L'\0'; + switch (*p) { + case L'-': + /* Trailing or initial '-' is not special. */ + if ((rangeStart == L'\0') || (p == end - 1)) { + if (*p == c) + return (match); + } else { + wchar_t rangeEnd = *++p; + if (rangeEnd == L'\\') + rangeEnd = *++p; + if ((rangeStart <= c) && (c <= rangeEnd)) + return (match); + } + break; + case L'\\': + ++p; + /* Fall through */ + default: + if (*p == c) + return (match); + nextRangeStart = *p; /* Possible start of range. */ + } + rangeStart = nextRangeStart; + ++p; + } + return (nomatch); +} + +/* + * If s is pointing to "./", ".//", "./././" or the like, skip it. + */ +static const char * +pm_slashskip(const char *s) { + while ((*s == '/') + || (s[0] == '.' && s[1] == '/') + || (s[0] == '.' && s[1] == '\0')) + ++s; + return (s); +} + +static const wchar_t * +pm_slashskip_w(const wchar_t *s) { + while ((*s == L'/') + || (s[0] == L'.' && s[1] == L'/') + || (s[0] == L'.' && s[1] == L'\0')) + ++s; + return (s); +} + +static int +pm(const char *p, const char *s, int flags) +{ + const char *end; + + /* + * Ignore leading './', './/', '././', etc. + */ + if (s[0] == '.' && s[1] == '/') + s = pm_slashskip(s + 1); + if (p[0] == '.' && p[1] == '/') + p = pm_slashskip(p + 1); + + for (;;) { + switch (*p) { + case '\0': + if (s[0] == '/') { + if (flags & PATHMATCH_NO_ANCHOR_END) + return (1); + /* "dir" == "dir/" == "dir/." */ + s = pm_slashskip(s); + } + return (*s == '\0'); + case '?': + /* ? always succeeds, unless we hit end of 's' */ + if (*s == '\0') + return (0); + break; + case '*': + /* "*" == "**" == "***" ... */ + while (*p == '*') + ++p; + /* Trailing '*' always succeeds. */ + if (*p == '\0') + return (1); + while (*s) { + if (archive_pathmatch(p, s, flags)) + return (1); + ++s; + } + return (0); + case '[': + /* + * Find the end of the [...] character class, + * ignoring \] that might occur within the class. + */ + end = p + 1; + while (*end != '\0' && *end != ']') { + if (*end == '\\' && end[1] != '\0') + ++end; + ++end; + } + if (*end == ']') { + /* We found [...], try to match it. */ + if (!pm_list(p + 1, end, *s, flags)) + return (0); + p = end; /* Jump to trailing ']' char. */ + break; + } else + /* No final ']', so just match '['. */ + if (*p != *s) + return (0); + break; + case '\\': + /* Trailing '\\' matches itself. */ + if (p[1] == '\0') { + if (*s != '\\') + return (0); + } else { + ++p; + if (*p != *s) + return (0); + } + break; + case '/': + if (*s != '/' && *s != '\0') + return (0); + /* Note: pattern "/\./" won't match "/"; + * pm_slashskip() correctly stops at backslash. */ + p = pm_slashskip(p); + s = pm_slashskip(s); + if (*p == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)) + return (1); + --p; /* Counteract the increment below. */ + --s; + break; + case '$': + /* '$' is special only at end of pattern and only + * if PATHMATCH_NO_ANCHOR_END is specified. */ + if (p[1] == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)){ + /* "dir" == "dir/" == "dir/." */ + return (*pm_slashskip(s) == '\0'); + } + /* Otherwise, '$' is not special. */ + /* FALL THROUGH */ + default: + if (*p != *s) + return (0); + break; + } + ++p; + ++s; + } +} + +static int +pm_w(const wchar_t *p, const wchar_t *s, int flags) +{ + const wchar_t *end; + + /* + * Ignore leading './', './/', '././', etc. + */ + if (s[0] == L'.' && s[1] == L'/') + s = pm_slashskip_w(s + 1); + if (p[0] == L'.' && p[1] == L'/') + p = pm_slashskip_w(p + 1); + + for (;;) { + switch (*p) { + case L'\0': + if (s[0] == L'/') { + if (flags & PATHMATCH_NO_ANCHOR_END) + return (1); + /* "dir" == "dir/" == "dir/." */ + s = pm_slashskip_w(s); + } + return (*s == L'\0'); + case L'?': + /* ? always succeeds, unless we hit end of 's' */ + if (*s == L'\0') + return (0); + break; + case L'*': + /* "*" == "**" == "***" ... */ + while (*p == L'*') + ++p; + /* Trailing '*' always succeeds. */ + if (*p == L'\0') + return (1); + while (*s) { + if (archive_pathmatch_w(p, s, flags)) + return (1); + ++s; + } + return (0); + case L'[': + /* + * Find the end of the [...] character class, + * ignoring \] that might occur within the class. + */ + end = p + 1; + while (*end != L'\0' && *end != L']') { + if (*end == L'\\' && end[1] != L'\0') + ++end; + ++end; + } + if (*end == L']') { + /* We found [...], try to match it. */ + if (!pm_list_w(p + 1, end, *s, flags)) + return (0); + p = end; /* Jump to trailing ']' char. */ + break; + } else + /* No final ']', so just match '['. */ + if (*p != *s) + return (0); + break; + case L'\\': + /* Trailing '\\' matches itself. */ + if (p[1] == L'\0') { + if (*s != L'\\') + return (0); + } else { + ++p; + if (*p != *s) + return (0); + } + break; + case L'/': + if (*s != L'/' && *s != L'\0') + return (0); + /* Note: pattern "/\./" won't match "/"; + * pm_slashskip() correctly stops at backslash. */ + p = pm_slashskip_w(p); + s = pm_slashskip_w(s); + if (*p == L'\0' && (flags & PATHMATCH_NO_ANCHOR_END)) + return (1); + --p; /* Counteract the increment below. */ + --s; + break; + case L'$': + /* '$' is special only at end of pattern and only + * if PATHMATCH_NO_ANCHOR_END is specified. */ + if (p[1] == L'\0' && (flags & PATHMATCH_NO_ANCHOR_END)){ + /* "dir" == "dir/" == "dir/." */ + return (*pm_slashskip_w(s) == L'\0'); + } + /* Otherwise, '$' is not special. */ + /* FALL THROUGH */ + default: + if (*p != *s) + return (0); + break; + } + ++p; + ++s; + } +} + +/* Main entry point. */ +int +__archive_pathmatch(const char *p, const char *s, int flags) +{ + /* Empty pattern only matches the empty string. */ + if (p == NULL || *p == '\0') + return (s == NULL || *s == '\0'); + + /* Leading '^' anchors the start of the pattern. */ + if (*p == '^') { + ++p; + flags &= ~PATHMATCH_NO_ANCHOR_START; + } + + if (*p == '/' && *s != '/') + return (0); + + /* Certain patterns and file names anchor implicitly. */ + if (*p == '*' || *p == '/' || *p == '/') { + while (*p == '/') + ++p; + while (*s == '/') + ++s; + return (pm(p, s, flags)); + } + + /* If start is unanchored, try to match start of each path element. */ + if (flags & PATHMATCH_NO_ANCHOR_START) { + for ( ; s != NULL; s = strchr(s, '/')) { + if (*s == '/') + s++; + if (pm(p, s, flags)) + return (1); + } + return (0); + } + + /* Default: Match from beginning. */ + return (pm(p, s, flags)); +} + +int +__archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags) +{ + /* Empty pattern only matches the empty string. */ + if (p == NULL || *p == L'\0') + return (s == NULL || *s == L'\0'); + + /* Leading '^' anchors the start of the pattern. */ + if (*p == L'^') { + ++p; + flags &= ~PATHMATCH_NO_ANCHOR_START; + } + + if (*p == L'/' && *s != L'/') + return (0); + + /* Certain patterns and file names anchor implicitly. */ + if (*p == L'*' || *p == L'/' || *p == L'/') { + while (*p == L'/') + ++p; + while (*s == L'/') + ++s; + return (pm_w(p, s, flags)); + } + + /* If start is unanchored, try to match start of each path element. */ + if (flags & PATHMATCH_NO_ANCHOR_START) { + for ( ; s != NULL; s = wcschr(s, L'/')) { + if (*s == L'/') + s++; + if (pm_w(p, s, flags)) + return (1); + } + return (0); + } + + /* Default: Match from beginning. */ + return (pm_w(p, s, flags)); +} diff --git a/Utilities/cmlibarchive/libarchive/archive_pathmatch.h b/Utilities/cmlibarchive/libarchive/archive_pathmatch.h new file mode 100644 index 000000000..e6901774d --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_pathmatch.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __LIBARCHIVE_BUILD +#ifndef __LIBARCHIVE_TEST +#error This header is only to be used internally to libarchive. +#endif +#endif + +#ifndef ARCHIVE_PATHMATCH_H +#define ARCHIVE_PATHMATCH_H + +/* Don't anchor at beginning unless the pattern starts with "^" */ +#define PATHMATCH_NO_ANCHOR_START 1 +/* Don't anchor at end unless the pattern ends with "$" */ +#define PATHMATCH_NO_ANCHOR_END 2 + +/* Note that "^" and "$" are not special unless you set the corresponding + * flag above. */ + +int __archive_pathmatch(const char *p, const char *s, int flags); +int __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags); + +#define archive_pathmatch(p, s, f) __archive_pathmatch(p, s, f) +#define archive_pathmatch_w(p, s, f) __archive_pathmatch_w(p, s, f) + +#endif diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd7.c b/Utilities/cmlibarchive/libarchive/archive_ppmd7.c index b2e8c3a34..fe0b0318c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_ppmd7.c +++ b/Utilities/cmlibarchive/libarchive/archive_ppmd7.c @@ -415,7 +415,7 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip) upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0)))); } - do + while (numPs != 0) { /* Create Child */ CTX_PTR c1; /* = AllocContext(p); */ @@ -435,7 +435,6 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip) SetSuccessor(ps[--numPs], REF(c1)); c = c1; } - while (numPs != 0); return c; } @@ -778,7 +777,7 @@ static void Range_Normalize(CPpmd7z_RangeDec *p) if(p->Range >= p->Bottom) break; else - p->Range = -p->Low & (p->Bottom - 1); + p->Range = ((uint32_t)(-(int32_t)p->Low)) & (p->Bottom - 1); } p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); p->Range <<= 8; @@ -991,7 +990,7 @@ static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p) p->Cache = (Byte)((UInt32)p->Low >> 24); } p->CacheSize++; - p->Low = (UInt32)p->Low << 8; + p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF; } static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total) diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h b/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h index 266676878..e78bde594 100644 --- a/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h @@ -152,7 +152,7 @@ typedef CPpmd_Byte_Ref; #define PPMD_SetAllBitsIn256Bytes(p) \ - { unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \ - p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }} + { unsigned j; for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \ + p[j+7] = p[j+6] = p[j+5] = p[j+4] = p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; }} #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_private.h b/Utilities/cmlibarchive/libarchive/archive_private.h index 9941e9661..30d472fcd 100644 --- a/Utilities/cmlibarchive/libarchive/archive_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_private.h @@ -50,6 +50,7 @@ #define ARCHIVE_READ_MAGIC (0xdeb0c5U) #define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U) #define ARCHIVE_READ_DISK_MAGIC (0xbadb0c5U) +#define ARCHIVE_MATCH_MAGIC (0xcad11c9U) #define ARCHIVE_STATE_NEW 1U #define ARCHIVE_STATE_HEADER 2U @@ -133,6 +134,7 @@ int __archive_check_magic(struct archive *, unsigned int magic, void __archive_errx(int retvalue, const char *msg) __LA_DEAD; +void __archive_ensure_cloexec_flag(int fd); int __archive_mktemp(const char *tmpdir); int __archive_clean(struct archive *); diff --git a/Utilities/cmlibarchive/libarchive/archive_rb.c b/Utilities/cmlibarchive/libarchive/archive_rb.c index f8035d9df..5b5da2034 100644 --- a/Utilities/cmlibarchive/libarchive/archive_rb.c +++ b/Utilities/cmlibarchive/libarchive/archive_rb.c @@ -96,7 +96,7 @@ __archive_rb_tree_init(struct archive_rb_tree *rbt, const struct archive_rb_tree_ops *ops) { rbt->rbt_ops = ops; - *((const struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE; + *((struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE; } struct archive_rb_node * @@ -237,6 +237,8 @@ __archive_rb_tree_reparent_nodes( struct archive_rb_node * const new_father = old_child; struct archive_rb_node * const new_child = old_father; + if (new_father == NULL) + return; /* * Exchange descendant linkages. */ @@ -377,13 +379,13 @@ __archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt, if (standin_father == self) { /* - * As a child of self, any childen would be opposite of + * As a child of self, any children would be opposite of * our parent. */ standin_son = standin->rb_nodes[standin_which]; } else { /* - * Since we aren't a child of self, any childen would be + * Since we aren't a child of self, any children would be * on the same side as our parent. */ standin_son = standin->rb_nodes[standin_other]; @@ -410,7 +412,7 @@ __archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt, /* * If we are about to delete the standin's father, then when * we call rebalance, we need to use ourselves as our father. - * Otherwise remember our original father. Also, sincef we are + * Otherwise remember our original father. Also, since we are * our standin's father we only need to reparent the standin's * brother. * @@ -466,7 +468,7 @@ __archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt, * __archive_rb_tree_node_swap(rbt, self, which); * __archive_rb_tree_prune_node(rbt, self, F); * - * But it's more efficient to just evalate and recolor the child. + * But it's more efficient to just evaluate and recolor the child. */ static void __archive_rb_tree_prune_blackred_branch( @@ -505,7 +507,7 @@ __archive_rb_tree_remove_node(struct archive_rb_tree *rbt, * red-black tree. So if we must remove a node, attempt to rearrange * the tree so we can remove a red node. * - * The simpliest case is a childless red node or a childless root node: + * The simplest case is a childless red node or a childless root node: * * | T --> T | or | R --> * | * | s --> * | @@ -517,7 +519,7 @@ __archive_rb_tree_remove_node(struct archive_rb_tree *rbt, } if (!RB_TWOCHILDREN_P(self)) { /* - * The next simpliest case is the node we are deleting is + * The next simplest case is the node we are deleting is * black and has one red child. * * | T --> T --> T | @@ -552,6 +554,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt, unsigned int other = which ^ RB_DIR_OTHER; struct archive_rb_node *brother = parent->rb_nodes[other]; + if (brother == NULL) + return;/* The tree may be broken. */ /* * For cases 1, 2a, and 2b, our brother's children must * be black and our father must be black @@ -573,6 +577,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt, */ __archive_rb_tree_reparent_nodes(parent, other); brother = parent->rb_nodes[other]; + if (brother == NULL) + return;/* The tree may be broken. */ } else { /* * Both our parent and brother are black. @@ -656,6 +662,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt, * If we had two red nephews, then after the swap, * our former father would have a red grandson. */ + if (brother->rb_nodes[other] == NULL) + return;/* The tree may be broken. */ RB_MARK_BLACK(brother->rb_nodes[other]); __archive_rb_tree_reparent_nodes(parent, other); break; /* We're done! */ @@ -683,7 +691,7 @@ __archive_rb_tree_iterate(struct archive_rb_tree *rbt, */ if (RB_SENTINEL_P(self->rb_nodes[direction])) { while (!RB_ROOT_P(rbt, self)) { - if (other == RB_POSITION(self)) + if (other == (unsigned int)RB_POSITION(self)) return RB_FATHER(self); self = RB_FATHER(self); } diff --git a/Utilities/cmlibarchive/libarchive/archive_read.3 b/Utilities/cmlibarchive/libarchive/archive_read.3 index 52851925c..a29cc1ea6 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read.3 @@ -22,14 +22,16 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $ +.\" $FreeBSD$ .\" -.Dd March 23, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_READ 3 .Os .Sh NAME .Nm archive_read .Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Sh DESCRIPTION diff --git a/Utilities/cmlibarchive/libarchive/archive_read.c b/Utilities/cmlibarchive/libarchive/archive_read.c index baf9dc467..796d37d06 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read.c +++ b/Utilities/cmlibarchive/libarchive/archive_read.c @@ -57,8 +57,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2 static int choose_filters(struct archive_read *); static int choose_format(struct archive_read *); -static void free_filters(struct archive_read *); -static int close_filters(struct archive_read *); static struct archive_vtable *archive_read_vtable(void); static int64_t _archive_filter_bytes(struct archive *, int); static int _archive_filter_code(struct archive *, int); @@ -194,14 +192,13 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request) int64_t get, ask = request; if (ask > skip_limit) ask = skip_limit; - get = (self->archive->client.skipper)(&self->archive->archive, - self->data, ask); + get = (self->archive->client.skipper) + (&self->archive->archive, self->data, ask); if (get == 0) return (total); request -= get; total += get; } - return total; } else if (self->archive->client.seeker != NULL && request > 64 * 1024) { /* If the client provided a seeker but not a skipper, @@ -216,8 +213,8 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request) * only do this for skips of over 64k. */ int64_t before = self->position; - int64_t after = (self->archive->client.seeker)(&self->archive->archive, - self->data, request, SEEK_CUR); + int64_t after = (self->archive->client.seeker) + (&self->archive->archive, self->data, request, SEEK_CUR); if (after != before + request) return ARCHIVE_FATAL; return after - before; @@ -242,14 +239,64 @@ client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence) static int client_close_proxy(struct archive_read_filter *self) { - int r = ARCHIVE_OK; + int r = ARCHIVE_OK, r2; + unsigned int i; + + if (self->archive->client.closer == NULL) + return (r); + for (i = 0; i < self->archive->client.nodes; i++) + { + r2 = (self->archive->client.closer) + ((struct archive *)self->archive, + self->archive->client.dataset[i].data); + if (r > r2) + r = r2; + } + return (r); +} - if (self->archive->client.closer != NULL) - r = (self->archive->client.closer)((struct archive *)self->archive, - self->data); +static int +client_open_proxy(struct archive_read_filter *self) +{ + int r = ARCHIVE_OK; + if (self->archive->client.opener != NULL) + r = (self->archive->client.opener)( + (struct archive *)self->archive, self->data); return (r); } +static int +client_switch_proxy(struct archive_read_filter *self, unsigned int iindex) +{ + int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK; + void *data2 = NULL; + + /* Don't do anything if already in the specified data node */ + if (self->archive->client.cursor == iindex) + return (ARCHIVE_OK); + + self->archive->client.cursor = iindex; + data2 = self->archive->client.dataset[self->archive->client.cursor].data; + if (self->archive->client.switcher != NULL) + { + r1 = r2 = (self->archive->client.switcher) + ((struct archive *)self->archive, self->data, data2); + self->data = data2; + } + else + { + /* Attempt to call close and open instead */ + if (self->archive->client.closer != NULL) + r1 = (self->archive->client.closer) + ((struct archive *)self->archive, self->data); + self->data = data2; + if (self->archive->client.opener != NULL) + r2 = (self->archive->client.opener) + ((struct archive *)self->archive, self->data); + } + return (r1 < r2) ? r1 : r2; +} + int archive_read_set_open_callback(struct archive *_a, archive_open_callback *client_opener) @@ -306,21 +353,109 @@ archive_read_set_close_callback(struct archive *_a, } int +archive_read_set_switch_callback(struct archive *_a, + archive_switch_callback *client_switcher) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_switch_callback"); + a->client.switcher = client_switcher; + return ARCHIVE_OK; +} + +int archive_read_set_callback_data(struct archive *_a, void *client_data) { + return archive_read_set_callback_data2(_a, client_data, 0); +} + +int +archive_read_set_callback_data2(struct archive *_a, void *client_data, + unsigned int iindex) +{ struct archive_read *a = (struct archive_read *)_a; archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, - "archive_read_set_callback_data"); - a->client.data = client_data; + "archive_read_set_callback_data2"); + + if (a->client.nodes == 0) + { + a->client.dataset = (struct archive_read_data_node *) + calloc(1, sizeof(*a->client.dataset)); + if (a->client.dataset == NULL) + { + archive_set_error(&a->archive, ENOMEM, + "No memory."); + return ARCHIVE_FATAL; + } + a->client.nodes = 1; + } + + if (iindex > a->client.nodes - 1) + { + archive_set_error(&a->archive, EINVAL, + "Invalid index specified."); + return ARCHIVE_FATAL; + } + a->client.dataset[iindex].data = client_data; + a->client.dataset[iindex].begin_position = -1; + a->client.dataset[iindex].total_size = -1; + return ARCHIVE_OK; +} + +int +archive_read_add_callback_data(struct archive *_a, void *client_data, + unsigned int iindex) +{ + struct archive_read *a = (struct archive_read *)_a; + void *p; + unsigned int i; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_add_callback_data"); + if (iindex > a->client.nodes) { + archive_set_error(&a->archive, EINVAL, + "Invalid index specified."); + return ARCHIVE_FATAL; + } + p = realloc(a->client.dataset, sizeof(*a->client.dataset) + * (++(a->client.nodes))); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory."); + return ARCHIVE_FATAL; + } + a->client.dataset = (struct archive_read_data_node *)p; + for (i = a->client.nodes - 1; i > iindex && i > 0; i--) { + a->client.dataset[i].data = a->client.dataset[i-1].data; + a->client.dataset[i].begin_position = -1; + a->client.dataset[i].total_size = -1; + } + a->client.dataset[iindex].data = client_data; + a->client.dataset[iindex].begin_position = -1; + a->client.dataset[iindex].total_size = -1; return ARCHIVE_OK; } int +archive_read_append_callback_data(struct archive *_a, void *client_data) +{ + struct archive_read *a = (struct archive_read *)_a; + return archive_read_add_callback_data(_a, client_data, a->client.nodes); +} + +int +archive_read_prepend_callback_data(struct archive *_a, void *client_data) +{ + return archive_read_add_callback_data(_a, client_data, 0); +} + +int archive_read_open1(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; - struct archive_read_filter *filter; + struct archive_read_filter *filter, *tmp; int slot, e; + unsigned int i; archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_open"); @@ -335,11 +470,14 @@ archive_read_open1(struct archive *_a) /* Open data source. */ if (a->client.opener != NULL) { - e =(a->client.opener)(&a->archive, a->client.data); + e = (a->client.opener)(&a->archive, a->client.dataset[0].data); if (e != 0) { /* If the open failed, call the closer to clean up. */ - if (a->client.closer) - (a->client.closer)(&a->archive, a->client.data); + if (a->client.closer) { + for (i = 0; i < a->client.nodes; i++) + (a->client.closer)(&a->archive, + a->client.dataset[i].data); + } return (e); } } @@ -350,31 +488,51 @@ archive_read_open1(struct archive *_a) filter->bidder = NULL; filter->upstream = NULL; filter->archive = a; - filter->data = a->client.data; + filter->data = a->client.dataset[0].data; + filter->open = client_open_proxy; filter->read = client_read_proxy; filter->skip = client_skip_proxy; filter->seek = client_seek_proxy; filter->close = client_close_proxy; + filter->sswitch = client_switch_proxy; filter->name = "none"; - filter->code = ARCHIVE_COMPRESSION_NONE; - a->filter = filter; + filter->code = ARCHIVE_FILTER_NONE; - /* Build out the input pipeline. */ - e = choose_filters(a); - if (e < ARCHIVE_WARN) { - a->archive.state = ARCHIVE_STATE_FATAL; - return (ARCHIVE_FATAL); + a->client.dataset[0].begin_position = 0; + if (!a->filter || !a->bypass_filter_bidding) + { + a->filter = filter; + /* Build out the input pipeline. */ + e = choose_filters(a); + if (e < ARCHIVE_WARN) { + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + } + else + { + /* Need to add "NONE" type filter at the end of the filter chain */ + tmp = a->filter; + while (tmp->upstream) + tmp = tmp->upstream; + tmp->upstream = filter; } - slot = choose_format(a); - if (slot < 0) { - close_filters(a); - a->archive.state = ARCHIVE_STATE_FATAL; - return (ARCHIVE_FATAL); + if (!a->format) + { + slot = choose_format(a); + if (slot < 0) { + __archive_read_close_filters(a); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + a->format = &(a->formats[slot]); } - a->format = &(a->formats[slot]); a->archive.state = ARCHIVE_STATE_HEADER; + + /* Ensure libarchive starts from the first node in a multivolume set */ + client_switch_proxy(a->filter, 0); return (e); } @@ -414,8 +572,8 @@ choose_filters(struct archive_read *a) /* Verify the filter by asking it for some data. */ __archive_read_filter_ahead(a->filter, 1, &avail); if (avail < 0) { - close_filters(a); - free_filters(a); + __archive_read_close_filters(a); + __archive_read_free_filters(a); return (ARCHIVE_FATAL); } a->archive.compression_name = a->filter->name; @@ -433,8 +591,8 @@ choose_filters(struct archive_read *a) a->filter = filter; r = (best_bidder->init)(a->filter); if (r != ARCHIVE_OK) { - close_filters(a); - free_filters(a); + __archive_read_close_filters(a); + __archive_read_free_filters(a); return (ARCHIVE_FATAL); } } @@ -502,6 +660,9 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) a->read_data_output_offset = 0; a->read_data_remaining = 0; + a->read_data_is_posix_read = 0; + a->read_data_requested = 0; + a->data_start_node = a->client.cursor; /* EOF always wins; otherwise return the worst error. */ return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1; } @@ -612,6 +773,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s) while (s > 0) { if (a->read_data_remaining == 0) { read_buf = a->read_data_block; + a->read_data_is_posix_read = 1; + a->read_data_requested = s; r = _archive_read_data_block(&a->archive, &read_buf, &a->read_data_remaining, &a->read_data_offset); a->read_data_block = read_buf; @@ -633,13 +796,13 @@ archive_read_data(struct archive *_a, void *buff, size_t s) } /* Compute the amount of zero padding needed. */ - if (a->read_data_output_offset + s < + if (a->read_data_output_offset + (int64_t)s < a->read_data_offset) { len = s; } else if (a->read_data_output_offset < a->read_data_offset) { - len = a->read_data_offset - - a->read_data_output_offset; + len = (size_t)(a->read_data_offset - + a->read_data_output_offset); } else len = 0; @@ -665,6 +828,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s) bytes_read += len; } } + a->read_data_is_posix_read = 0; + a->read_data_requested = 0; return (bytes_read); } @@ -699,6 +864,23 @@ archive_read_data_skip(struct archive *_a) return (r); } +int64_t +archive_seek_data(struct archive *_a, int64_t offset, int whence) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, + "archive_seek_data_block"); + + if (a->format->seek_data == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: " + "No format_seek_data_block function registered"); + return (ARCHIVE_FATAL); + } + + return (a->format->seek_data)(a, offset, whence); +} + /* * Read the next block of entry data from the archive. * This is a zero-copy interface; the client receives a pointer, @@ -725,8 +907,8 @@ _archive_read_data_block(struct archive *_a, return (a->format->read_data)(a, buff, size, offset); } -static int -close_filters(struct archive_read *a) +int +__archive_read_close_filters(struct archive_read *a) { struct archive_read_filter *f = a->filter; int r = ARCHIVE_OK; @@ -746,8 +928,8 @@ close_filters(struct archive_read *a) return r; } -static void -free_filters(struct archive_read *a) +void +__archive_read_free_filters(struct archive_read *a) { while (a->filter != NULL) { struct archive_read_filter *t = a->filter->upstream; @@ -791,7 +973,7 @@ _archive_read_close(struct archive *_a) /* TODO: Clean up the formatters. */ /* Release the filter objects. */ - r1 = close_filters(a); + r1 = __archive_read_close_filters(a); if (r1 < r) r = r1; @@ -830,7 +1012,7 @@ _archive_read_free(struct archive *_a) } /* Free the filters */ - free_filters(a); + __archive_read_free_filters(a); /* Release the bidder objects. */ n = sizeof(a->bidders)/sizeof(a->bidders[0]); @@ -847,6 +1029,7 @@ _archive_read_free(struct archive *_a) archive_entry_free(a->entry); a->archive.magic = 0; __archive_clean(&a->archive); + free(a->client.dataset); free(a); return (r); } @@ -856,7 +1039,8 @@ get_filter(struct archive *_a, int n) { struct archive_read *a = (struct archive_read *)_a; struct archive_read_filter *f = a->filter; - /* We use n == -1 for 'the last filter', which is always the client proxy. */ + /* We use n == -1 for 'the last filter', which is always the + * client proxy. */ if (n == -1 && f != NULL) { struct archive_read_filter *last = f; f = f->upstream; @@ -909,6 +1093,7 @@ __archive_read_register_format(struct archive_read *a, int (*read_header)(struct archive_read *, struct archive_entry *), int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *), int (*read_data_skip)(struct archive_read *), + int64_t (*seek_data)(struct archive_read *, int64_t, int), int (*cleanup)(struct archive_read *)) { int i, number_slots; @@ -928,6 +1113,7 @@ __archive_read_register_format(struct archive_read *a, a->formats[i].read_header = read_header; a->formats[i].read_data = read_data; a->formats[i].read_data_skip = read_data_skip; + a->formats[i].seek_data = seek_data; a->formats[i].cleanup = cleanup; a->formats[i].data = format_data; a->formats[i].name = name; @@ -1074,7 +1260,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter, if (filter->next > filter->buffer && filter->next + min > filter->buffer + filter->buffer_size) { if (filter->avail > 0) - memmove(filter->buffer, filter->next, filter->avail); + memmove(filter->buffer, filter->next, + filter->avail); filter->next = filter->buffer; } @@ -1089,15 +1276,26 @@ __archive_read_filter_ahead(struct archive_read_filter *filter, &filter->client_buff); if (bytes_read < 0) { /* Read error. */ filter->client_total = filter->client_avail = 0; - filter->client_next = filter->client_buff = NULL; + filter->client_next = + filter->client_buff = NULL; filter->fatal = 1; if (avail != NULL) *avail = ARCHIVE_FATAL; return (NULL); } - if (bytes_read == 0) { /* Premature end-of-file. */ + if (bytes_read == 0) { + /* Check for another client object first */ + if (filter->archive->client.cursor != + filter->archive->client.nodes - 1) { + if (client_switch_proxy(filter, + filter->archive->client.cursor + 1) + == ARCHIVE_OK) + continue; + } + /* Premature end-of-file. */ filter->client_total = filter->client_avail = 0; - filter->client_next = filter->client_buff = NULL; + filter->client_next = + filter->client_buff = NULL; filter->end_of_file = 1; /* Return whatever we do have. */ if (avail != NULL) @@ -1107,9 +1305,7 @@ __archive_read_filter_ahead(struct archive_read_filter *filter, filter->client_total = bytes_read; filter->client_avail = filter->client_total; filter->client_next = filter->client_buff; - } - else - { + } else { /* * We can't satisfy the request from the copy * buffer or the existing client data, so we @@ -1130,9 +1326,10 @@ __archive_read_filter_ahead(struct archive_read_filter *filter, t *= 2; if (t <= s) { /* Integer overflow! */ archive_set_error( - &filter->archive->archive, - ENOMEM, - "Unable to allocate copy buffer"); + &filter->archive->archive, + ENOMEM, + "Unable to allocate copy" + " buffer"); filter->fatal = 1; if (avail != NULL) *avail = ARCHIVE_FATAL; @@ -1171,8 +1368,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter, if (tocopy > filter->client_avail) tocopy = filter->client_avail; - memcpy(filter->next + filter->avail, filter->client_next, - tocopy); + memcpy(filter->next + filter->avail, + filter->client_next, tocopy); /* Remove this data from client buffer. */ filter->client_next += tocopy; filter->client_avail -= tocopy; @@ -1231,7 +1428,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request) /* Use up the copy buffer first. */ if (filter->avail > 0) { - min = minimum(request, (int64_t)filter->avail); + min = (size_t)minimum(request, (int64_t)filter->avail); filter->next += min; filter->avail -= min; request -= min; @@ -1241,7 +1438,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request) /* Then use up the client buffer. */ if (filter->client_avail > 0) { - min = minimum(request, (int64_t)filter->client_avail); + min = (size_t)minimum(request, (int64_t)filter->client_avail); filter->client_next += min; filter->client_avail -= min; request -= min; @@ -1275,6 +1472,13 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request) } if (bytes_read == 0) { + if (filter->archive->client.cursor != + filter->archive->client.nodes - 1) { + if (client_switch_proxy(filter, + filter->archive->client.cursor + 1) + == ARCHIVE_OK) + continue; + } filter->client_buff = NULL; filter->end_of_file = 1; return (total_bytes_skipped); @@ -1283,7 +1487,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request) if (bytes_read >= request) { filter->client_next = ((const char *)filter->client_buff) + request; - filter->client_avail = bytes_read - request; + filter->client_avail = (size_t)(bytes_read - request); filter->client_total = bytes_read; total_bytes_skipped += request; filter->position += request; @@ -1306,15 +1510,109 @@ __archive_read_seek(struct archive_read *a, int64_t offset, int whence) } int64_t -__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset, int whence) +__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset, + int whence) { + struct archive_read_client *client; int64_t r; + unsigned int cursor; if (filter->closed || filter->fatal) return (ARCHIVE_FATAL); if (filter->seek == NULL) return (ARCHIVE_FAILED); - r = filter->seek(filter, offset, whence); + + client = &(filter->archive->client); + switch (whence) { + case SEEK_CUR: + /* Adjust the offset and use SEEK_SET instead */ + offset += filter->position; + case SEEK_SET: + cursor = 0; + while (1) + { + if (client->dataset[cursor].begin_position < 0 || + client->dataset[cursor].total_size < 0 || + client->dataset[cursor].begin_position + + client->dataset[cursor].total_size - 1 > offset || + cursor + 1 >= client->nodes) + break; + r = client->dataset[cursor].begin_position + + client->dataset[cursor].total_size; + client->dataset[++cursor].begin_position = r; + } + while (1) { + r = client_switch_proxy(filter, cursor); + if (r != ARCHIVE_OK) + return r; + if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0) + return r; + client->dataset[cursor].total_size = r; + if (client->dataset[cursor].begin_position + + client->dataset[cursor].total_size - 1 > offset || + cursor + 1 >= client->nodes) + break; + r = client->dataset[cursor].begin_position + + client->dataset[cursor].total_size; + client->dataset[++cursor].begin_position = r; + } + offset -= client->dataset[cursor].begin_position; + if (offset < 0) + offset = 0; + else if (offset > client->dataset[cursor].total_size - 1) + offset = client->dataset[cursor].total_size - 1; + if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0) + return r; + break; + + case SEEK_END: + cursor = 0; + while (1) { + if (client->dataset[cursor].begin_position < 0 || + client->dataset[cursor].total_size < 0 || + cursor + 1 >= client->nodes) + break; + r = client->dataset[cursor].begin_position + + client->dataset[cursor].total_size; + client->dataset[++cursor].begin_position = r; + } + while (1) { + r = client_switch_proxy(filter, cursor); + if (r != ARCHIVE_OK) + return r; + if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0) + return r; + client->dataset[cursor].total_size = r; + r = client->dataset[cursor].begin_position + + client->dataset[cursor].total_size; + if (cursor + 1 >= client->nodes) + break; + client->dataset[++cursor].begin_position = r; + } + while (1) { + if (r + offset >= + client->dataset[cursor].begin_position) + break; + offset += client->dataset[cursor].total_size; + if (cursor == 0) + break; + cursor--; + r = client->dataset[cursor].begin_position + + client->dataset[cursor].total_size; + } + offset = (r + offset) - client->dataset[cursor].begin_position; + if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK) + return r; + r = client_seek_proxy(filter, offset, SEEK_SET); + if (r < ARCHIVE_OK) + return r; + break; + + default: + return (ARCHIVE_FATAL); + } + r += client->dataset[cursor].begin_position; + if (r >= 0) { /* * Ouch. Clearing the buffer like this hurts, especially diff --git a/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c new file mode 100644 index 000000000..017d7c68a --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c @@ -0,0 +1,198 @@ +/*- + * Copyright (c) 2003-2012 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +int +archive_read_append_filter(struct archive *_a, int code) +{ + int r1, r2, number_bidders, i; + char str[20]; + struct archive_read_filter_bidder *bidder; + struct archive_read_filter *filter; + struct archive_read *a = (struct archive_read *)_a; + + r1 = r2 = (ARCHIVE_OK); + switch (code) + { + case ARCHIVE_FILTER_NONE: + /* No filter to add, so do nothing. + * NOTE: An initial "NONE" type filter is always set at the end of the + * filter chain. + */ + r1 = (ARCHIVE_OK); + break; + case ARCHIVE_FILTER_GZIP: + strcpy(str, "gzip"); + r1 = archive_read_support_filter_gzip(_a); + break; + case ARCHIVE_FILTER_BZIP2: + strcpy(str, "bzip2"); + r1 = archive_read_support_filter_bzip2(_a); + break; + case ARCHIVE_FILTER_COMPRESS: + strcpy(str, "compress (.Z)"); + r1 = archive_read_support_filter_compress(_a); + break; + case ARCHIVE_FILTER_PROGRAM: + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Cannot append program filter using archive_read_append_filter"); + return (ARCHIVE_FATAL); + case ARCHIVE_FILTER_LZMA: + strcpy(str, "lzma"); + r1 = archive_read_support_filter_lzma(_a); + break; + case ARCHIVE_FILTER_XZ: + strcpy(str, "xz"); + r1 = archive_read_support_filter_xz(_a); + break; + case ARCHIVE_FILTER_UU: + strcpy(str, "uu"); + r1 = archive_read_support_filter_uu(_a); + break; + case ARCHIVE_FILTER_RPM: + strcpy(str, "rpm"); + r1 = archive_read_support_filter_rpm(_a); + break; + case ARCHIVE_FILTER_LZIP: + strcpy(str, "lzip"); + r1 = archive_read_support_filter_lzip(_a); + break; + case ARCHIVE_FILTER_LRZIP: + strcpy(str, "lrzip"); + r1 = archive_read_support_filter_lrzip(_a); + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Invalid filter code specified"); + return (ARCHIVE_FATAL); + } + + if (code != ARCHIVE_FILTER_NONE) + { + number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); + + bidder = a->bidders; + for (i = 0; i < number_bidders; i++, bidder++) + { + if (!bidder->name || !strcmp(bidder->name, str)) + break; + } + if (!bidder->name || strcmp(bidder->name, str)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: Unable to append filter"); + return (ARCHIVE_FATAL); + } + + filter + = (struct archive_read_filter *)calloc(1, sizeof(*filter)); + if (filter == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + filter->bidder = bidder; + filter->archive = a; + filter->upstream = a->filter; + a->filter = filter; + r2 = (bidder->init)(a->filter); + if (r2 != ARCHIVE_OK) { + __archive_read_close_filters(a); + __archive_read_free_filters(a); + return (ARCHIVE_FATAL); + } + } + + a->bypass_filter_bidding = 1; + return (r1 < r2) ? r1 : r2; +} + +int +archive_read_append_filter_program(struct archive *_a, const char *cmd) +{ + return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0)); +} + +int +archive_read_append_filter_program_signature(struct archive *_a, + const char *cmd, const void *signature, size_t signature_len) +{ + int r, number_bidders, i; + struct archive_read_filter_bidder *bidder; + struct archive_read_filter *filter; + struct archive_read *a = (struct archive_read *)_a; + + if (archive_read_support_filter_program_signature(_a, cmd, signature, + signature_len) != (ARCHIVE_OK)) + return (ARCHIVE_FATAL); + + number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); + + bidder = a->bidders; + for (i = 0; i < number_bidders; i++, bidder++) + { + /* Program bidder name set to filter name after initialization */ + if (bidder->data && !bidder->name) + break; + } + if (!bidder->data) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: Unable to append program filter"); + return (ARCHIVE_FATAL); + } + + filter + = (struct archive_read_filter *)calloc(1, sizeof(*filter)); + if (filter == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + filter->bidder = bidder; + filter->archive = a; + filter->upstream = a->filter; + a->filter = filter; + r = (bidder->init)(a->filter); + if (r != ARCHIVE_OK) { + __archive_read_close_filters(a); + __archive_read_free_filters(a); + return (ARCHIVE_FATAL); + } + bidder->name = a->filter->name; + + a->bypass_filter_bidding = 1; + return r; +} diff --git a/Utilities/cmlibarchive/libarchive/archive_read_data.3 b/Utilities/cmlibarchive/libarchive/archive_read_data.3 index 78d049782..bf0578ce3 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_data.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_data.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 22, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_READ_DATA 3 .Os .Sh NAME @@ -33,6 +33,8 @@ .Nm archive_read_data_skip , .Nm archive_read_data_into_fd .Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft ssize_t diff --git a/Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c b/Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c index 14f941070..b4398f1ec 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c @@ -64,7 +64,7 @@ pad_to(struct archive *a, int fd, int can_lseek, } while (target_offset > actual_offset) { to_write = nulls_size; - if (target_offset < actual_offset + nulls_size) + if (target_offset < actual_offset + (int64_t)nulls_size) to_write = (size_t)(target_offset - actual_offset); bytes_written = write(fd, nulls, to_write); if (bytes_written < 0) { diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk.3 b/Utilities/cmlibarchive/libarchive/archive_read_disk.3 index 3c49bffc8..525dc59cb 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk.3 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_read_disk.3 190957 2009-04-12 05:04:02Z kientzle $ +.\" $FreeBSD$ .\" -.Dd March 10, 2009 +.Dd February 2, 2012 .Dt ARCHIVE_READ_DISK 3 .Os .Sh NAME @@ -42,6 +42,8 @@ .Nm archive_read_finish , .Nm archive_read_free .Nd functions for reading objects from disk +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft struct archive * diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c index fdeb5166d..e984aaadb 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2009 Tim Kientzle - * Copyright (c) 2010 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,8 +49,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif -#ifdef HAVE_SYS_XATTR_H +#if defined(HAVE_SYS_XATTR_H) #include <sys/xattr.h> +#elif defined(HAVE_ATTR_XATTR_H) +#include <attr/xattr.h> #endif #ifdef HAVE_SYS_EA_H #include <sys/ea.h> @@ -58,9 +60,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #ifdef HAVE_ACL_LIBACL_H #include <acl/libacl.h> #endif -#ifdef HAVE_ATTR_XATTR_H -#include <attr/xattr.h> -#endif #ifdef HAVE_COPYFILE_H #include <copyfile.h> #endif @@ -104,6 +103,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #include "archive_private.h" #include "archive_read_disk_private.h" +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + /* * Linux and FreeBSD plug this obvious hole in POSIX.1e in * different ways. @@ -114,14 +117,14 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #define ACL_GET_PERM acl_get_perm_np #endif -static int setup_acls_posix1e(struct archive_read_disk *, - struct archive_entry *, int fd); +static int setup_acls(struct archive_read_disk *, + struct archive_entry *, int *fd); static int setup_mac_metadata(struct archive_read_disk *, - struct archive_entry *, int fd); + struct archive_entry *, int *fd); static int setup_xattrs(struct archive_read_disk *, - struct archive_entry *, int fd); + struct archive_entry *, int *fd); static int setup_sparse(struct archive_read_disk *, - struct archive_entry *, int fd); + struct archive_entry *, int *fd); int archive_read_disk_entry_from_file(struct archive *_a, @@ -190,11 +193,18 @@ archive_read_disk_entry_from_file(struct archive *_a, * this is an extra step, it has a nice side-effect: We get an * open file descriptor which we can use in the subsequent lookups. */ if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) { - if (fd < 0) - fd = open(path, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + if (a->tree != NULL) + fd = a->open_on_current_dir(a->tree, path, + O_RDONLY | O_NONBLOCK | O_CLOEXEC); + else + fd = open(path, O_RDONLY | O_NONBLOCK | + O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); + } if (fd >= 0) { - unsigned long stflags; - int r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags); + int stflags; + r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags); if (r == 0 && stflags != 0) archive_entry_set_fflags(entry, stflags, 0); } @@ -213,13 +223,21 @@ archive_read_disk_entry_from_file(struct archive *_a, "Couldn't read link data"); return (ARCHIVE_FAILED); } + if (a->tree != NULL) { #ifdef HAVE_READLINKAT - if (a->entry_wd_fd >= 0) - lnklen = readlinkat(a->entry_wd_fd, path, - linkbuffer, linkbuffer_len); - else + lnklen = readlinkat(a->tree_current_dir_fd(a->tree), + path, linkbuffer, linkbuffer_len); +#else + if (a->tree_enter_working_dir(a->tree) != 0) { + archive_set_error(&a->archive, errno, + "Couldn't read link data"); + free(linkbuffer); + return (ARCHIVE_FAILED); + } + lnklen = readlink(path, linkbuffer, linkbuffer_len); #endif /* HAVE_READLINKAT */ - lnklen = readlink(path, linkbuffer, linkbuffer_len); + } else + lnklen = readlink(path, linkbuffer, linkbuffer_len); if (lnklen < 0) { archive_set_error(&a->archive, errno, "Couldn't read link data"); @@ -232,14 +250,16 @@ archive_read_disk_entry_from_file(struct archive *_a, } #endif /* HAVE_READLINK || HAVE_READLINKAT */ - r = setup_acls_posix1e(a, entry, fd); - r1 = setup_xattrs(a, entry, fd); - if (r1 < r) - r = r1; - r1 = setup_mac_metadata(a, entry, fd); + r = setup_acls(a, entry, &fd); + r1 = setup_xattrs(a, entry, &fd); if (r1 < r) r = r1; - r1 = setup_sparse(a, entry, fd); + if (a->enable_copyfile) { + r1 = setup_mac_metadata(a, entry, &fd); + if (r1 < r) + r = r1; + } + r1 = setup_sparse(a, entry, &fd); if (r1 < r) r = r1; @@ -265,16 +285,18 @@ archive_read_disk_entry_from_file(struct archive *_a, */ static int setup_mac_metadata(struct archive_read_disk *a, - struct archive_entry *entry, int fd) + struct archive_entry *entry, int *fd) { int tempfd = -1; int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR; struct stat copyfile_stat; int ret = ARCHIVE_OK; - void *buff; + void *buff = NULL; int have_attrs; - const char *name, *tempdir, *tempfile = NULL; + const char *name, *tempdir; + struct archive_string tempfile; + (void)fd; /* UNUSED */ name = archive_entry_sourcepath(entry); if (name == NULL) name = archive_entry_pathname(entry); @@ -284,6 +306,14 @@ setup_mac_metadata(struct archive_read_disk *a, return (ARCHIVE_WARN); } + if (a->tree != NULL) { + if (a->tree_enter_working_dir(a->tree) != 0) { + archive_set_error(&a->archive, errno, + "Couldn't change dir"); + return (ARCHIVE_FAILED); + } + } + /* Short-circuit if there's nothing to do. */ have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK); if (have_attrs == -1) { @@ -299,25 +329,28 @@ setup_mac_metadata(struct archive_read_disk *a, tempdir = getenv("TMPDIR"); if (tempdir == NULL) tempdir = _PATH_TMP; - tempfile = tempnam(tempdir, "tar.md."); + archive_string_init(&tempfile); + archive_strcpy(&tempfile, tempdir); + archive_strcat(&tempfile, "tar.md.XXXXXX"); + tempfd = mkstemp(tempfile.s); + if (tempfd < 0) { + archive_set_error(&a->archive, errno, + "Could not open extended attribute file"); + ret = ARCHIVE_WARN; + goto cleanup; + } + __archive_ensure_cloexec_flag(tempfd); /* XXX I wish copyfile() could pack directly to a memory * buffer; that would avoid the temp file here. For that * matter, it would be nice if fcopyfile() actually worked, * that would reduce the many open/close races here. */ - if (copyfile(name, tempfile, 0, copyfile_flags | COPYFILE_PACK)) { + if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) { archive_set_error(&a->archive, errno, "Could not pack extended attributes"); ret = ARCHIVE_WARN; goto cleanup; } - tempfd = open(tempfile, O_RDONLY); - if (tempfd < 0) { - archive_set_error(&a->archive, errno, - "Could not open extended attribute file"); - ret = ARCHIVE_WARN; - goto cleanup; - } if (fstat(tempfd, ©file_stat)) { archive_set_error(&a->archive, errno, "Could not check size of extended attributes"); @@ -340,10 +373,12 @@ setup_mac_metadata(struct archive_read_disk *a, archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size); cleanup: - if (tempfd >= 0) + if (tempfd >= 0) { close(tempfd); - if (tempfile != NULL) - unlink(tempfile); + unlink(tempfile.s); + } + archive_string_free(&tempfile); + free(buff); return (ret); } @@ -354,7 +389,7 @@ cleanup: */ static int setup_mac_metadata(struct archive_read_disk *a, - struct archive_entry *entry, int fd) + struct archive_entry *entry, int *fd) { (void)a; /* UNUSED */ (void)entry; /* UNUSED */ @@ -364,16 +399,19 @@ setup_mac_metadata(struct archive_read_disk *a, #endif -#ifdef HAVE_POSIX_ACL -static void setup_acl_posix1e(struct archive_read_disk *a, +#if defined(HAVE_POSIX_ACL) && defined(ACL_TYPE_NFS4) +static int translate_acl(struct archive_read_disk *a, struct archive_entry *entry, acl_t acl, int archive_entry_acl_type); static int -setup_acls_posix1e(struct archive_read_disk *a, - struct archive_entry *entry, int fd) +setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) { const char *accpath; acl_t acl; +#if HAVE_ACL_IS_TRIVIAL_NP + int r; +#endif accpath = archive_entry_sourcepath(entry); if (accpath == NULL) @@ -381,9 +419,38 @@ setup_acls_posix1e(struct archive_read_disk *a, archive_entry_acl_clear(entry); + /* Try NFS4 ACL first. */ + if (*fd >= 0) + acl = acl_get_fd(*fd); +#if HAVE_ACL_GET_LINK_NP + else if (!a->follow_symlinks) + acl = acl_get_link_np(accpath, ACL_TYPE_NFS4); +#else + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one. */ + acl = NULL; +#endif + else + acl = acl_get_file(accpath, ACL_TYPE_NFS4); +#if HAVE_ACL_IS_TRIVIAL_NP + /* Ignore "trivial" ACLs that just mirror the file mode. */ + acl_is_trivial_np(acl, &r); + if (r) { + acl_free(acl); + acl = NULL; + } +#endif + if (acl != NULL) { + translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); + acl_free(acl); + return (ARCHIVE_OK); + } + /* Retrieve access ACL from file. */ - if (fd >= 0) - acl = acl_get_fd(fd); + if (*fd >= 0) + acl = acl_get_fd(*fd); #if HAVE_ACL_GET_LINK_NP else if (!a->follow_symlinks) acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS); @@ -397,7 +464,7 @@ setup_acls_posix1e(struct archive_read_disk *a, else acl = acl_get_file(accpath, ACL_TYPE_ACCESS); if (acl != NULL) { - setup_acl_posix1e(a, entry, acl, + translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); acl_free(acl); } @@ -406,7 +473,7 @@ setup_acls_posix1e(struct archive_read_disk *a, if (S_ISDIR(archive_entry_mode(entry))) { acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); if (acl != NULL) { - setup_acl_posix1e(a, entry, acl, + translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); acl_free(acl); } @@ -415,69 +482,181 @@ setup_acls_posix1e(struct archive_read_disk *a, } /* - * Translate POSIX.1e ACL into libarchive internal structure. + * Translate system ACL into libarchive internal structure. */ -static void -setup_acl_posix1e(struct archive_read_disk *a, - struct archive_entry *entry, acl_t acl, int archive_entry_acl_type) + +static struct { + int archive_perm; + int platform_perm; +} acl_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, + {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +}; + +static struct { + int archive_inherit; + int platform_inherit; +} acl_inherit_map[] = { + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY} +}; + +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, acl_t acl, int default_entry_acl_type) { acl_tag_t acl_tag; + acl_entry_type_t acl_type; + acl_flagset_t acl_flagset; acl_entry_t acl_entry; acl_permset_t acl_permset; + int brand, i, r, entry_acl_type; int s, ae_id, ae_tag, ae_perm; const char *ae_name; + + // FreeBSD "brands" ACLs as POSIX.1e or NFSv4 + // Make sure the "brand" on this ACL is consistent + // with the default_entry_acl_type bits provided. + acl_get_brand_np(acl, &brand); + switch (brand) { + case ACL_BRAND_POSIX: + switch (default_entry_acl_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + break; + default: + // XXX set warning message? + return ARCHIVE_FAILED; + } + break; + case ACL_BRAND_NFS4: + if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + // XXX set warning message? + return ARCHIVE_FAILED; + } + break; + default: + // XXX set warning message? + return ARCHIVE_FAILED; + break; + } + + s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); while (s == 1) { ae_id = -1; ae_name = NULL; + ae_perm = 0; acl_get_tag_type(acl_entry, &acl_tag); - if (acl_tag == ACL_USER) { + switch (acl_tag) { + case ACL_USER: ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry); ae_name = archive_read_disk_uname(&a->archive, ae_id); ae_tag = ARCHIVE_ENTRY_ACL_USER; - } else if (acl_tag == ACL_GROUP) { + break; + case ACL_GROUP: ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry); ae_name = archive_read_disk_gname(&a->archive, ae_id); ae_tag = ARCHIVE_ENTRY_ACL_GROUP; - } else if (acl_tag == ACL_MASK) { + break; + case ACL_MASK: ae_tag = ARCHIVE_ENTRY_ACL_MASK; - } else if (acl_tag == ACL_USER_OBJ) { + break; + case ACL_USER_OBJ: ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - } else if (acl_tag == ACL_GROUP_OBJ) { + break; + case ACL_GROUP_OBJ: ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - } else if (acl_tag == ACL_OTHER) { + break; + case ACL_OTHER: ae_tag = ARCHIVE_ENTRY_ACL_OTHER; - } else { + break; + case ACL_EVERYONE: + ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; + break; + default: /* Skip types that libarchive can't support. */ + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); continue; } - acl_get_permset(acl_entry, &acl_permset); - ae_perm = 0; + // XXX acl type maps to allow/deny/audit/YYYY bits + // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for + // non-NFSv4 ACLs + entry_acl_type = default_entry_acl_type; + r = acl_get_entry_type_np(acl_entry, &acl_type); + if (r == 0) { + switch (acl_type) { + case ACL_ENTRY_TYPE_ALLOW: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + break; + case ACL_ENTRY_TYPE_DENY: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + break; + case ACL_ENTRY_TYPE_AUDIT: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; + break; + case ACL_ENTRY_TYPE_ALARM: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + break; + } + } + /* - * acl_get_perm() is spelled differently on different - * platforms; see above. + * Libarchive stores "flag" (NFSv4 inheritance bits) + * in the ae_perm bitmap. */ - if (ACL_GET_PERM(acl_permset, ACL_EXECUTE)) - ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE; - if (ACL_GET_PERM(acl_permset, ACL_READ)) - ae_perm |= ARCHIVE_ENTRY_ACL_READ; - if (ACL_GET_PERM(acl_permset, ACL_WRITE)) - ae_perm |= ARCHIVE_ENTRY_ACL_WRITE; + acl_get_flagset_np(acl_entry, &acl_flagset); + for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { + if (acl_get_flag_np(acl_flagset, + acl_inherit_map[i].platform_inherit)) + ae_perm |= acl_inherit_map[i].archive_inherit; - archive_entry_acl_add_entry(entry, - archive_entry_acl_type, ae_perm, ae_tag, - ae_id, ae_name); + } + + acl_get_permset(acl_entry, &acl_permset); + for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { + /* + * acl_get_perm() is spelled differently on different + * platforms; see above. + */ + if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm)) + ae_perm |= acl_perm_map[i].archive_perm; + } + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, + ae_id, ae_name); s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); } + return (ARCHIVE_OK); } #else static int -setup_acls_posix1e(struct archive_read_disk *a, - struct archive_entry *entry, int fd) +setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) { (void)a; /* UNUSED */ (void)entry; /* UNUSED */ @@ -571,7 +750,7 @@ setup_xattr(struct archive_read_disk *a, static int setup_xattrs(struct archive_read_disk *a, - struct archive_entry *entry, int fd) + struct archive_entry *entry, int *fd) { char *list, *p; const char *path; @@ -581,16 +760,30 @@ setup_xattrs(struct archive_read_disk *a, if (path == NULL) path = archive_entry_pathname(entry); + if (*fd < 0 && a->tree != NULL) { + if (a->follow_symlinks || + archive_entry_filetype(entry) != AE_IFLNK) + *fd = a->open_on_current_dir(a->tree, path, + O_RDONLY | O_NONBLOCK); + if (*fd < 0) { + if (a->tree_enter_working_dir(a->tree) != 0) { + archive_set_error(&a->archive, errno, + "Couldn't access %s", path); + return (ARCHIVE_FAILED); + } + } + } + #if HAVE_FLISTXATTR - if (fd >= 0) - list_size = flistxattr(fd, NULL, 0); + if (*fd >= 0) + list_size = flistxattr(*fd, NULL, 0); else if (!a->follow_symlinks) list_size = llistxattr(path, NULL, 0); else list_size = listxattr(path, NULL, 0); #elif HAVE_FLISTEA - if (fd >= 0) - list_size = flistea(fd, NULL, 0); + if (*fd >= 0) + list_size = flistea(*fd, NULL, 0); else if (!a->follow_symlinks) list_size = llistea(path, NULL, 0); else @@ -614,15 +807,15 @@ setup_xattrs(struct archive_read_disk *a, } #if HAVE_FLISTXATTR - if (fd >= 0) - list_size = flistxattr(fd, list, list_size); + if (*fd >= 0) + list_size = flistxattr(*fd, list, list_size); else if (!a->follow_symlinks) list_size = llistxattr(path, list, list_size); else list_size = listxattr(path, list, list_size); #elif HAVE_FLISTEA - if (fd >= 0) - list_size = flistea(fd, list, list_size); + if (*fd >= 0) + list_size = flistea(*fd, list, list_size); else if (!a->follow_symlinks) list_size = llistea(path, list, list_size); else @@ -640,7 +833,7 @@ setup_xattrs(struct archive_read_disk *a, if (strncmp(p, "system.", 7) == 0 || strncmp(p, "xfsroot.", 8) == 0) continue; - setup_xattr(a, entry, p, fd); + setup_xattr(a, entry, p, *fd); } free(list); @@ -701,6 +894,7 @@ setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, size = extattr_get_file(accpath, namespace, name, value, size); if (size == -1) { + free(value); archive_set_error(&a->archive, errno, "Couldn't read extended attribute"); return (ARCHIVE_WARN); @@ -714,7 +908,7 @@ setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, static int setup_xattrs(struct archive_read_disk *a, - struct archive_entry *entry, int fd) + struct archive_entry *entry, int *fd) { char buff[512]; char *list, *p; @@ -726,8 +920,22 @@ setup_xattrs(struct archive_read_disk *a, if (path == NULL) path = archive_entry_pathname(entry); - if (fd >= 0) - list_size = extattr_list_fd(fd, namespace, NULL, 0); + if (*fd < 0 && a->tree != NULL) { + if (a->follow_symlinks || + archive_entry_filetype(entry) != AE_IFLNK) + *fd = a->open_on_current_dir(a->tree, path, + O_RDONLY | O_NONBLOCK); + if (*fd < 0) { + if (a->tree_enter_working_dir(a->tree) != 0) { + archive_set_error(&a->archive, errno, + "Couldn't access %s", path); + return (ARCHIVE_FAILED); + } + } + } + + if (*fd >= 0) + list_size = extattr_list_fd(*fd, namespace, NULL, 0); else if (!a->follow_symlinks) list_size = extattr_list_link(path, namespace, NULL, 0); else @@ -749,8 +957,8 @@ setup_xattrs(struct archive_read_disk *a, return (ARCHIVE_FATAL); } - if (fd >= 0) - list_size = extattr_list_fd(fd, namespace, list, list_size); + if (*fd >= 0) + list_size = extattr_list_fd(*fd, namespace, list, list_size); else if (!a->follow_symlinks) list_size = extattr_list_link(path, namespace, list, list_size); else @@ -772,7 +980,7 @@ setup_xattrs(struct archive_read_disk *a, name = buff + strlen(buff); memcpy(name, p + 1, len); name[len] = '\0'; - setup_xattr(a, entry, namespace, name, buff, fd); + setup_xattr(a, entry, namespace, name, buff, *fd); p += 1 + len; } @@ -787,7 +995,7 @@ setup_xattrs(struct archive_read_disk *a, */ static int setup_xattrs(struct archive_read_disk *a, - struct archive_entry *entry, int fd) + struct archive_entry *entry, int *fd) { (void)a; /* UNUSED */ (void)entry; /* UNUSED */ @@ -816,14 +1024,13 @@ setup_xattrs(struct archive_read_disk *a, static int setup_sparse(struct archive_read_disk *a, - struct archive_entry *entry, int fd) + struct archive_entry *entry, int *fd) { char buff[4096]; struct fiemap *fm; struct fiemap_extent *fe; int64_t size; int count, do_fiemap; - int initial_fd = fd; int exit_sts = ARCHIVE_OK; if (archive_entry_filetype(entry) != AE_IFREG @@ -831,20 +1038,27 @@ setup_sparse(struct archive_read_disk *a, || archive_entry_hardlink(entry) != NULL) return (ARCHIVE_OK); - if (fd < 0) { + if (*fd < 0) { const char *path; path = archive_entry_sourcepath(entry); if (path == NULL) path = archive_entry_pathname(entry); - fd = open(path, O_RDONLY | O_NONBLOCK); - if (fd < 0) { + if (a->tree != NULL) + *fd = a->open_on_current_dir(a->tree, path, + O_RDONLY | O_NONBLOCK | O_CLOEXEC); + else + *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (*fd < 0) { archive_set_error(&a->archive, errno, "Can't open `%s'", path); return (ARCHIVE_FAILED); } + __archive_ensure_cloexec_flag(*fd); } + /* Initialize buffer to avoid the error valgrind complains about. */ + memset(buff, 0, sizeof(buff)); count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe); fm = (struct fiemap *)buff; fm->fm_start = 0; @@ -856,29 +1070,22 @@ setup_sparse(struct archive_read_disk *a, for (;;) { int i, r; - r = ioctl(fd, FS_IOC_FIEMAP, fm); + r = ioctl(*fd, FS_IOC_FIEMAP, fm); if (r < 0) { - /* When errno is ENOTTY, it is better we should - * return ARCHIVE_OK because an earlier version - *(<2.6.28) cannot perfom FS_IOC_FIEMAP. - * We should also check if errno is EOPNOTSUPP, - * it means "Operation not supported". */ - if (errno != ENOTTY && errno != EOPNOTSUPP) { - archive_set_error(&a->archive, errno, - "FIEMAP failed"); - exit_sts = ARCHIVE_FAILED; - } + /* When something error happens, it is better we + * should return ARCHIVE_OK because an earlier + * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */ goto exit_setup_sparse; } if (fm->fm_mapped_extents == 0) break; fe = fm->fm_extents; - for (i = 0; i < fm->fm_mapped_extents; i++, fe++) { + for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) { if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) { /* The fe_length of the last block does not * adjust itself to its size files. */ int64_t length = fe->fe_length; - if (fe->fe_logical + length > size) + if (fe->fe_logical + length > (uint64_t)size) length -= fe->fe_logical + length - size; if (fe->fe_logical == 0 && length == size) { /* This is not sparse. */ @@ -899,8 +1106,6 @@ setup_sparse(struct archive_read_disk *a, break; } exit_setup_sparse: - if (initial_fd != fd) - close(fd); return (exit_sts); } @@ -912,10 +1117,9 @@ exit_setup_sparse: static int setup_sparse(struct archive_read_disk *a, - struct archive_entry *entry, int fd) + struct archive_entry *entry, int *fd) { int64_t size; - int initial_fd = fd; off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */ off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */ int exit_sts = ARCHIVE_OK; @@ -926,33 +1130,50 @@ setup_sparse(struct archive_read_disk *a, return (ARCHIVE_OK); /* Does filesystem support the reporting of hole ? */ - if (fd >= 0) { - if (fpathconf(fd, _PC_MIN_HOLE_SIZE) <= 0) + if (*fd < 0 && a->tree != NULL) { + const char *path; + + path = archive_entry_sourcepath(entry); + if (path == NULL) + path = archive_entry_pathname(entry); + *fd = a->open_on_current_dir(a->tree, path, + O_RDONLY | O_NONBLOCK); + if (*fd < 0) { + archive_set_error(&a->archive, errno, + "Can't open `%s'", path); + return (ARCHIVE_FAILED); + } + } + + if (*fd >= 0) { + if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); - initial_off = lseek(fd, 0, SEEK_CUR); + initial_off = lseek(*fd, 0, SEEK_CUR); if (initial_off != 0) - lseek(fd, 0, SEEK_SET); + lseek(*fd, 0, SEEK_SET); } else { const char *path; path = archive_entry_sourcepath(entry); if (path == NULL) path = archive_entry_pathname(entry); + if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); - fd = open(path, O_RDONLY | O_NONBLOCK); - if (fd < 0) { + *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (*fd < 0) { archive_set_error(&a->archive, errno, "Can't open `%s'", path); return (ARCHIVE_FAILED); } + __archive_ensure_cloexec_flag(*fd); initial_off = 0; } off_s = 0; size = archive_entry_size(entry); while (off_s < size) { - off_s = lseek(fd, off_s, SEEK_DATA); + off_s = lseek(*fd, off_s, SEEK_DATA); if (off_s == (off_t)-1) { if (errno == ENXIO) break;/* no more hole */ @@ -961,10 +1182,10 @@ setup_sparse(struct archive_read_disk *a, exit_sts = ARCHIVE_FAILED; goto exit_setup_sparse; } - off_e = lseek(fd, off_s, SEEK_HOLE); - if (off_s == (off_t)-1) { + off_e = lseek(*fd, off_s, SEEK_HOLE); + if (off_e == (off_t)-1) { if (errno == ENXIO) { - off_e = lseek(fd, 0, SEEK_END); + off_e = lseek(*fd, 0, SEEK_END); if (off_e != (off_t)-1) break;/* no more data */ } @@ -980,10 +1201,7 @@ setup_sparse(struct archive_read_disk *a, off_s = off_e; } exit_setup_sparse: - if (initial_fd != fd) - close(fd); - else - lseek(fd, initial_off, SEEK_SET); + lseek(*fd, initial_off, SEEK_SET); return (exit_sts); } @@ -994,7 +1212,7 @@ exit_setup_sparse: */ static int setup_sparse(struct archive_read_disk *a, - struct archive_entry *entry, int fd) + struct archive_entry *entry, int *fd) { (void)a; /* UNUSED */ (void)entry; /* UNUSED */ diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c index 365a874a9..a13dbbf81 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2009 Tim Kientzle - * Copyright (c) 2010,2011 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,6 +52,19 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_LINUX_MAGIC_H #include <linux/magic.h> #endif +#ifdef HAVE_LINUX_FS_H +#include <linux/fs.h> +#endif +/* + * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. + * As the include guards don't agree, the order of include is important. + */ +#ifdef HAVE_LINUX_EXT2_FS_H +#include <linux/ext2_fs.h> /* for Linux file flags */ +#endif +#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) +#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */ +#endif #ifdef HAVE_DIRECT_H #include <direct.h> #endif @@ -76,6 +89,9 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif #include "archive.h" #include "archive_string.h" @@ -89,6 +105,9 @@ __FBSDID("$FreeBSD$"); #ifndef O_BINARY #define O_BINARY 0 #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif /*- * This is a new directory-walking system that addresses a number @@ -222,6 +241,7 @@ struct tree { char symlink_mode; struct filesystem *current_filesystem; struct filesystem *filesystem_table; + int initial_filesystem_id; int current_filesystem_id; int max_filesystem_id; int allocated_filesytem; @@ -240,6 +260,7 @@ struct tree { #define onWorkingDir 64 /* We are on the working dir where we are * reading directory entry at this time. */ #define needsRestoreTimes 128 +#define onInitialDir 256 /* We are on the initial dir. */ static int tree_dir_next_posix(struct tree *t); @@ -342,6 +363,8 @@ static const char *trivial_lookup_uname(void *, int64_t uid); static int setup_sparse(struct archive_read_disk *, struct archive_entry *); static int close_and_restore_time(int fd, struct tree *, struct restore_time *); +static int open_on_current_dir(struct tree *, const char *, int); +static int tree_dup(int); static struct archive_vtable * @@ -430,16 +453,19 @@ archive_read_disk_new(void) { struct archive_read_disk *a; - a = (struct archive_read_disk *)malloc(sizeof(*a)); + a = (struct archive_read_disk *)calloc(1, sizeof(*a)); if (a == NULL) return (NULL); - memset(a, 0, sizeof(*a)); a->archive.magic = ARCHIVE_READ_DISK_MAGIC; a->archive.state = ARCHIVE_STATE_NEW; a->archive.vtable = archive_read_disk_vtable(); a->lookup_uname = trivial_lookup_uname; a->lookup_gname = trivial_lookup_gname; - a->entry_wd_fd = -1; + a->enable_copyfile = 1; + a->traverse_mount_points = 1; + a->open_on_current_dir = open_on_current_dir; + a->tree_current_dir_fd = tree_current_dir_fd; + a->tree_enter_working_dir = tree_enter_working_dir; return (&a->archive); } @@ -555,6 +581,37 @@ archive_read_disk_set_atime_restored(struct archive *_a) #endif } +int +archive_read_disk_set_behavior(struct archive *_a, int flags) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + int r = ARCHIVE_OK; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump"); + + if (flags & ARCHIVE_READDISK_RESTORE_ATIME) + r = archive_read_disk_set_atime_restored(_a); + else { + a->restore_time = 0; + if (a->tree != NULL) + a->tree->flags &= ~needsRestoreTimes; + } + if (flags & ARCHIVE_READDISK_HONOR_NODUMP) + a->honor_nodump = 1; + else + a->honor_nodump = 0; + if (flags & ARCHIVE_READDISK_MAC_COPYFILE) + a->enable_copyfile = 1; + else + a->enable_copyfile = 0; + if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) + a->traverse_mount_points = 0; + else + a->traverse_mount_points = 1; + return (r); +} + /* * Trivial implementations of gname/uname lookup functions. * These are normally overridden by the client, but these stub @@ -664,7 +721,7 @@ _archive_read_data_block(struct archive *_a, const void **buff, * Open the current file. */ if (t->entry_fd < 0) { - int flags = O_RDONLY | O_BINARY; + int flags = O_RDONLY | O_BINARY | O_CLOEXEC; /* * Eliminate or reduce cache effects if we can. @@ -685,13 +742,9 @@ _archive_read_data_block(struct archive *_a, const void **buff, flags |= O_NOATIME; do { #endif -#ifdef HAVE_OPENAT - t->entry_fd = openat(tree_current_dir_fd(t), + t->entry_fd = open_on_current_dir(t, tree_current_access_path(t), flags); -#else - tree_enter_working_dir(t); - t->entry_fd = open(tree_current_access_path(t), flags); -#endif + __archive_ensure_cloexec_flag(t->entry_fd); #if defined(O_NOATIME) /* * When we did open the file with O_NOATIME flag, @@ -733,7 +786,7 @@ _archive_read_data_block(struct archive *_a, const void **buff, t->entry_buff_size = t->current_filesystem->buff_size; buffbytes = t->entry_buff_size; - if (buffbytes > t->current_sparse->length) + if ((int64_t)buffbytes > t->current_sparse->length) buffbytes = t->current_sparse->length; /* @@ -802,29 +855,17 @@ abort_read_data: } static int -_archive_read_next_header2(struct archive *_a, struct archive_entry *entry) +next_entry(struct archive_read_disk *a, struct tree *t, + struct archive_entry *entry) { - struct archive_read_disk *a = (struct archive_read_disk *)_a; - struct tree *t; const struct stat *st; /* info to use for this entry */ const struct stat *lst;/* lstat() information */ - int descend, fd = -1, r; - - archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, - ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, - "archive_read_next_header2"); + const char *name; + int descend, r; - t = a->tree; - if (t->entry_fd >= 0) { - close_and_restore_time(t->entry_fd, t, &t->restore_time); - t->entry_fd = -1; - } -#if !(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)) - /* Restore working directory. */ - tree_enter_working_dir(t); -#endif st = NULL; lst = NULL; + t->descend = 0; do { switch (tree_next(t)) { case TREE_ERROR_FATAL: @@ -859,6 +900,38 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) } } while (lst == NULL); +#ifdef __APPLE__ + if (a->enable_copyfile) { + /* If we're using copyfile(), ignore "._XXX" files. */ + const char *bname = strrchr(tree_current_path(t), '/'); + if (bname == NULL) + bname = tree_current_path(t); + else + ++bname; + if (bname[0] == '.' && bname[1] == '_') + return (ARCHIVE_RETRY); + } +#endif + + archive_entry_copy_pathname(entry, tree_current_path(t)); + /* + * Perform path matching. + */ + if (a->matching) { + r = archive_match_path_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Faild : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + /* * Distinguish 'L'/'P'/'H' symlink following. */ @@ -897,13 +970,46 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) tree_enter_initial_dir(t); return (ARCHIVE_FATAL); } + if (t->initial_filesystem_id == -1) + t->initial_filesystem_id = t->current_filesystem_id; + if (!a->traverse_mount_points) { + if (t->initial_filesystem_id != t->current_filesystem_id) + return (ARCHIVE_RETRY); + } t->descend = descend; - archive_entry_set_pathname(entry, tree_current_path(t)); - archive_entry_copy_sourcepath(entry, tree_current_access_path(t)); + /* + * Honor nodump flag. + * If the file is marked with nodump flag, do not return this entry. + */ + if (a->honor_nodump) { +#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) + if (st->st_flags & UF_NODUMP) + return (ARCHIVE_RETRY); +#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\ + defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) + if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) { + int stflags; + + t->entry_fd = open_on_current_dir(t, + tree_current_access_path(t), + O_RDONLY | O_NONBLOCK | O_CLOEXEC); + __archive_ensure_cloexec_flag(t->entry_fd); + if (t->entry_fd >= 0) { + r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS, + &stflags); + if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0) + return (ARCHIVE_RETRY); + } + } +#endif + } + archive_entry_copy_stat(entry, st); - /* Save the times to be restored. */ + /* Save the times to be restored. This must be in before + * calling archive_read_disk_descend() or any chance of it, + * especially, invokng a callback. */ t->restore_time.mtime = archive_entry_mtime(entry); t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry); t->restore_time.atime = archive_entry_atime(entry); @@ -911,39 +1017,102 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) t->restore_time.filetype = archive_entry_filetype(entry); t->restore_time.noatime = t->current_filesystem->noatime; -#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR) /* - * Open the current file to freely gather its metadata anywhere in - * working directory. - * Note: A symbolic link file cannot be opened with O_NOFOLLOW. + * Perform time matching. */ - if (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK) - fd = openat(tree_current_dir_fd(t), tree_current_access_path(t), - O_RDONLY | O_NONBLOCK); - /* Restore working directory if openat() operation failed or - * the file is a symbolic link. */ - if (fd < 0) - tree_enter_working_dir(t); + if (a->matching) { + r = archive_match_time_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Faild : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } - /* The current directory fd is needed at - * archive_read_disk_entry_from_file() function to read link data - * with readlinkat(). */ - a->entry_wd_fd = tree_current_dir_fd(t); -#endif + /* Lookup uname/gname */ + name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry)); + if (name != NULL) + archive_entry_copy_uname(entry, name); + name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry)); + if (name != NULL) + archive_entry_copy_gname(entry, name); + + /* + * Perform owner matching. + */ + if (a->matching) { + r = archive_match_owner_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Faild : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + + /* + * Invoke a meta data filter callback. + */ + if (a->metadata_filter_func) { + if (!a->metadata_filter_func(&(a->archive), + a->metadata_filter_data, entry)) + return (ARCHIVE_RETRY); + } /* * Populate the archive_entry with metadata from the disk. */ - r = archive_read_disk_entry_from_file(&(a->archive), entry, fd, st); + archive_entry_copy_sourcepath(entry, tree_current_access_path(t)); + r = archive_read_disk_entry_from_file(&(a->archive), entry, + t->entry_fd, st); - /* Close the file descriptor used for reding the current file - * metadata at archive_read_disk_entry_from_file(). */ - if (fd >= 0) - close(fd); + return (r); +} + +static int +_archive_read_next_header2(struct archive *_a, struct archive_entry *entry) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t; + int r; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_next_header2"); + + t = a->tree; + if (t->entry_fd >= 0) { + close_and_restore_time(t->entry_fd, t, &t->restore_time); + t->entry_fd = -1; + } + + for (;;) { + r = next_entry(a, t, entry); + if (t->entry_fd >= 0) { + close(t->entry_fd); + t->entry_fd = -1; + } + + if (r == ARCHIVE_RETRY) { + archive_entry_clear(entry); + continue; + } + break; + } /* Return to the initial directory. */ tree_enter_initial_dir(t); - archive_entry_copy_sourcepath(entry, tree_current_path(t)); /* * EOF and FATAL are persistent at this layer. By @@ -956,6 +1125,8 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) break; case ARCHIVE_OK: case ARCHIVE_WARN: + /* Overwrite the sourcepath based on the initial directory. */ + archive_entry_copy_sourcepath(entry, tree_current_path(t)); t->entry_total = 0; if (archive_entry_filetype(entry) == AE_IFREG) { t->nlink = archive_entry_nlink(entry); @@ -1018,6 +1189,48 @@ setup_sparse(struct archive_read_disk *a, struct archive_entry *entry) return (ARCHIVE_OK); } +int +archive_read_disk_set_matching(struct archive *_a, struct archive *_ma, + void (*_excluded_func)(struct archive *, void *, struct archive_entry *), + void *_client_data) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_matching"); + a->matching = _ma; + a->excluded_cb_func = _excluded_func; + a->excluded_cb_data = _client_data; + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_metadata_filter_callback(struct archive *_a, + int (*_metadata_filter_func)(struct archive *, void *, + struct archive_entry *), void *_client_data) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, + "archive_read_disk_set_metadata_filter_callback"); + + a->metadata_filter_func = _metadata_filter_func; + a->metadata_filter_data = _client_data; + return (ARCHIVE_OK); +} + +int +archive_read_disk_can_descend(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t = a->tree; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_disk_can_descend"); + + return (t->visit_type == TREE_REGULAR && t->descend); +} + /* * Called by the client to mark the directory just returned from * tree_next() as needing to be visited. @@ -1028,14 +1241,12 @@ archive_read_disk_descend(struct archive *_a) struct archive_read_disk *a = (struct archive_read_disk *)_a; struct tree *t = a->tree; - archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, "archive_read_disk_descend"); - if (t->visit_type != TREE_REGULAR || !t->descend) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Ignored the request descending the current object"); - return (ARCHIVE_WARN); - } + if (t->visit_type != TREE_REGULAR || !t->descend) + return (ARCHIVE_OK); if (tree_current_is_physical_dir(t)) { tree_push(t, t->basename, t->current_filesystem_id, @@ -1079,8 +1290,12 @@ archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname) archive_string_init(&path); if (archive_string_append_from_wcs(&path, pathname, wcslen(pathname)) != 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Can't convert a path to a char string"); + if (errno == ENOMEM) + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't convert a path to a char string"); a->archive.state = ARCHIVE_STATE_FATAL; ret = ARCHIVE_FATAL; } else @@ -1151,15 +1366,17 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) fid = t->max_filesystem_id++; if (t->max_filesystem_id > t->allocated_filesytem) { size_t s; + void *p; s = t->max_filesystem_id * 2; - t->filesystem_table = realloc(t->filesystem_table, - s * sizeof(*t->filesystem_table)); - if (t->filesystem_table == NULL) { + p = realloc(t->filesystem_table, + s * sizeof(*t->filesystem_table)); + if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate tar data"); return (ARCHIVE_FATAL); } + t->filesystem_table = (struct filesystem *)p; t->allocated_filesytem = s; } t->current_filesystem_id = fid; @@ -1268,13 +1485,14 @@ setup_current_filesystem(struct archive_read_disk *a) t->current_filesystem->synthetic = -1; t->current_filesystem->remote = -1; if (tree_current_is_symblic_link_target(t)) { -#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR) +#if defined(HAVE_OPENAT) /* * Get file system statistics on any directory * where current is. */ int fd = openat(tree_current_dir_fd(t), - tree_current_access_path(t), O_RDONLY); + tree_current_access_path(t), O_RDONLY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); if (fd < 0) { archive_set_error(&a->archive, errno, "openat failed"); @@ -1285,6 +1503,10 @@ setup_current_filesystem(struct archive_read_disk *a) xr = get_xfer_size(t, fd, NULL); close(fd); #else + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } r = statfs(tree_current_access_path(t), &sfs); if (r == 0) xr = get_xfer_size(t, -1, tree_current_access_path(t)); @@ -1334,9 +1556,13 @@ setup_current_filesystem(struct archive_read_disk *a) t->current_filesystem->name_max = sfs.f_namemax; #else /* Mac OS X does not have f_namemax in struct statfs. */ - if (tree_current_is_symblic_link_target(t)) + if (tree_current_is_symblic_link_target(t)) { + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); - else + } else nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); if (nm == -1) t->current_filesystem->name_max = NAME_MAX; @@ -1360,6 +1586,10 @@ setup_current_filesystem(struct archive_read_disk *a) int r, xr = 0; t->current_filesystem->synthetic = -1; + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } if (tree_current_is_symblic_link_target(t)) { r = statvfs(tree_current_access_path(t), &sfs); if (r == 0) @@ -1434,13 +1664,14 @@ setup_current_filesystem(struct archive_read_disk *a) int r, vr = 0, xr = 0; if (tree_current_is_symblic_link_target(t)) { -#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR) +#if defined(HAVE_OPENAT) /* * Get file system statistics on any directory * where current is. */ int fd = openat(tree_current_dir_fd(t), - tree_current_access_path(t), O_RDONLY); + tree_current_access_path(t), O_RDONLY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); if (fd < 0) { archive_set_error(&a->archive, errno, "openat failed"); @@ -1452,6 +1683,10 @@ setup_current_filesystem(struct archive_read_disk *a) xr = get_xfer_size(t, fd, NULL); close(fd); #else + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } vr = statvfs(tree_current_access_path(t), &svfs); r = statfs(tree_current_access_path(t), &sfs); if (r == 0) @@ -1463,9 +1698,11 @@ setup_current_filesystem(struct archive_read_disk *a) r = fstatfs(tree_current_dir_fd(t), &sfs); if (r == 0) xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); -#elif defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR) -#error "Unexpected case. Please tell us about this error." #else + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } vr = statvfs(".", &svfs); r = statfs(".", &sfs); if (r == 0) @@ -1536,13 +1773,14 @@ setup_current_filesystem(struct archive_read_disk *a) t->current_filesystem->synthetic = -1;/* Not supported */ t->current_filesystem->remote = -1;/* Not supported */ if (tree_current_is_symblic_link_target(t)) { -#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR) +#if defined(HAVE_OPENAT) /* * Get file system statistics on any directory * where current is. */ int fd = openat(tree_current_dir_fd(t), - tree_current_access_path(t), O_RDONLY); + tree_current_access_path(t), O_RDONLY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); if (fd < 0) { archive_set_error(&a->archive, errno, "openat failed"); @@ -1553,6 +1791,10 @@ setup_current_filesystem(struct archive_read_disk *a) xr = get_xfer_size(t, fd, NULL); close(fd); #else + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } r = statvfs(tree_current_access_path(t), &sfs); if (r == 0) xr = get_xfer_size(t, -1, tree_current_access_path(t)); @@ -1562,9 +1804,11 @@ setup_current_filesystem(struct archive_read_disk *a) r = fstatvfs(tree_current_dir_fd(t), &sfs); if (r == 0) xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); -#elif defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR) -#error "Unexpected case. Please tell us about this error." #else + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } r = statvfs(".", &sfs); if (r == 0) xr = get_xfer_size(t, -1, "."); @@ -1622,9 +1866,13 @@ setup_current_filesystem(struct archive_read_disk *a) #if defined(HAVE_READDIR_R) /* Set maximum filename length. */ # if defined(_PC_NAME_MAX) - if (tree_current_is_symblic_link_target(t)) + if (tree_current_is_symblic_link_target(t)) { + if (tree_enter_working_dir(t) != 0) { + archive_set_error(&a->archive, errno, "fchdir failed"); + return (ARCHIVE_FAILED); + } nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); - else + } else nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); if (nm == -1) # endif /* _PC_NAME_MAX */ @@ -1653,7 +1901,8 @@ static int close_and_restore_time(int fd, struct tree *t, struct restore_time *rt) { #ifndef HAVE_UTIMES - (void)a; /* UNUSED */ + (void)t; /* UNUSED */ + (void)rt; /* UNUSED */ return (close(fd)); #else #if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__) @@ -1704,6 +1953,40 @@ close_and_restore_time(int fd, struct tree *t, struct restore_time *rt) return (0); } +static int +open_on_current_dir(struct tree *t, const char *path, int flags) +{ +#ifdef HAVE_OPENAT + return (openat(tree_current_dir_fd(t), path, flags)); +#else + if (tree_enter_working_dir(t) != 0) + return (-1); + return (open(path, flags)); +#endif +} + +static int +tree_dup(int fd) +{ + int new_fd; +#ifdef F_DUPFD_CLOEXEC + static volatile int can_dupfd_cloexec = 1; + + if (can_dupfd_cloexec) { + new_fd = fcntl(fd, F_DUPFD_CLOEXEC); + if (new_fd != -1) + return (new_fd); + /* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC, + * but it cannot be used. So we have to try dup(). */ + /* We won't try F_DUPFD_CLOEXEC. */ + can_dupfd_cloexec = 0; + } +#endif /* F_DUPFD_CLOEXEC */ + new_fd = dup(fd); + __archive_ensure_cloexec_flag(new_fd); + return (new_fd); +} + /* * Add a directory path to the current stack. */ @@ -1785,6 +2068,7 @@ static struct tree * tree_reopen(struct tree *t, const char *path, int restore_time) { t->flags = (restore_time)?needsRestoreTimes:0; + t->flags |= onInitialDir; t->visit_type = 0; t->tree_errno = 0; t->dirname_length = 0; @@ -1797,25 +2081,30 @@ tree_reopen(struct tree *t, const char *path, int restore_time) t->entry_fd = -1; t->entry_eof = 0; t->entry_remaining_bytes = 0; + t->initial_filesystem_id = -1; /* First item is set up a lot like a symlink traversal. */ tree_push(t, path, 0, 0, 0, NULL); t->stack->flags = needsFirstVisit; t->maxOpenCount = t->openCount = 1; - t->initial_dir_fd = open(".", O_RDONLY); - t->working_dir_fd = dup(t->initial_dir_fd); + t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC); + __archive_ensure_cloexec_flag(t->initial_dir_fd); + t->working_dir_fd = tree_dup(t->initial_dir_fd); return (t); } static int tree_descent(struct tree *t) { - int r = 0; + int flag, new_fd, r = 0; -#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR) - int new_fd; t->dirname_length = archive_strlen(&t->path); - new_fd = openat(t->working_dir_fd, t->stack->name.s, O_RDONLY); + flag = O_RDONLY | O_CLOEXEC; +#if defined(O_DIRECTORY) + flag |= O_DIRECTORY; +#endif + new_fd = open_on_current_dir(t, t->stack->name.s, flag); + __archive_ensure_cloexec_flag(new_fd); if (new_fd < 0) { t->tree_errno = errno; r = TREE_ERROR_DIR; @@ -1829,30 +2118,10 @@ tree_descent(struct tree *t) t->maxOpenCount = t->openCount; } else close(t->working_dir_fd); + /* Renew the current working directory. */ t->working_dir_fd = new_fd; + t->flags &= ~onWorkingDir; } -#else - /* If it is a link, set up fd for the ascent. */ - if (t->stack->flags & isDirLink) - t->stack->symlink_parent_fd = t->working_dir_fd; - else { - close(t->working_dir_fd); - t->openCount--; - } - t->working_dir_fd = -1; - t->dirname_length = archive_strlen(&t->path); - if (chdir(t->stack->name.s) != 0) - { - t->tree_errno = errno; - r = TREE_ERROR_DIR; - } else { - t->depth++; - t->working_dir_fd = open(".", O_RDONLY); - t->openCount++; - if (t->openCount > t->maxOpenCount) - t->maxOpenCount = t->openCount; - } -#endif return (r); } @@ -1863,37 +2132,23 @@ static int tree_ascend(struct tree *t) { struct tree_entry *te; - int r = 0, prev_dir_fd; + int new_fd, r = 0, prev_dir_fd; te = t->stack; prev_dir_fd = t->working_dir_fd; -#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR) if (te->flags & isDirLink) - t->working_dir_fd = te->symlink_parent_fd; + new_fd = te->symlink_parent_fd; else { - int new_fd = openat(t->working_dir_fd, "..", O_RDONLY); - if (new_fd < 0) { - t->tree_errno = errno; - r = TREE_ERROR_FATAL; - } else - t->working_dir_fd = new_fd; + new_fd = open_on_current_dir(t, "..", O_RDONLY | O_CLOEXEC); + __archive_ensure_cloexec_flag(new_fd); } -#else - if (te->flags & isDirLink) { - if (fchdir(te->symlink_parent_fd) != 0) { - t->tree_errno = errno; - r = TREE_ERROR_FATAL; - } else - t->working_dir_fd = te->symlink_parent_fd; + if (new_fd < 0) { + t->tree_errno = errno; + r = TREE_ERROR_FATAL; } else { - if (chdir("..") != 0) { - t->tree_errno = errno; - r = TREE_ERROR_FATAL; - } else - t->working_dir_fd = open(".", O_RDONLY); - } -#endif - if (r == 0) { + /* Renew the current working directory. */ + t->working_dir_fd = new_fd; + t->flags &= ~onWorkingDir; /* Current directory has been changed, we should * close an fd of previous working directory. */ close_and_restore_time(prev_dir_fd, t, &te->restore_time); @@ -1914,10 +2169,12 @@ tree_enter_initial_dir(struct tree *t) { int r = 0; - if (t->flags & onWorkingDir) { + if ((t->flags & onInitialDir) == 0) { r = fchdir(t->initial_dir_fd); - if (r == 0) + if (r == 0) { t->flags &= ~onWorkingDir; + t->flags |= onInitialDir; + } } return (r); } @@ -1937,8 +2194,10 @@ tree_enter_working_dir(struct tree *t) */ if (t->depth > 0 && (t->flags & onWorkingDir) == 0) { r = fchdir(t->working_dir_fd); - if (r == 0) + if (r == 0) { + t->flags &= ~onInitialDir; t->flags |= onWorkingDir; + } } return (r); } @@ -2045,10 +2304,16 @@ tree_dir_next_posix(struct tree *t) #endif #if defined(HAVE_FDOPENDIR) - if ((t->d = fdopendir(dup(t->working_dir_fd))) == NULL) { -#else - if ((t->d = opendir(".")) == NULL) { + t->d = fdopendir(tree_dup(t->working_dir_fd)); +#else /* HAVE_FDOPENDIR */ + if (tree_enter_working_dir(t) == 0) { + t->d = opendir("."); +#if HAVE_DIRFD || defined(dirfd) + __archive_ensure_cloexec_flag(dirfd(t->d)); #endif + } +#endif /* HAVE_FDOPENDIR */ + if (t->d == NULL) { r = tree_ascend(t); /* Undo "chdir" */ tree_pop(t); t->tree_errno = errno; @@ -2075,11 +2340,21 @@ tree_dir_next_posix(struct tree *t) #endif /* HAVE_READDIR_R */ } for (;;) { + errno = 0; #if defined(HAVE_READDIR_R) r = readdir_r(t->d, t->dirent, &t->de); +#ifdef _AIX + /* Note: According to the man page, return value 9 indicates + * that the readdir_r was not successful and the error code + * is set to the global errno variable. And then if the end + * of directory entries was reached, the return value is 9 + * and the third parameter is set to NULL and errno is + * unchanged. */ + if (r == 9) + r = errno; +#endif /* _AIX */ if (r != 0 || t->de == NULL) { #else - errno = 0; t->de = readdir(t->d); if (t->de == NULL) { r = errno; @@ -2118,6 +2393,8 @@ tree_current_stat(struct tree *t) if (fstatat(tree_current_dir_fd(t), tree_current_access_path(t), &t->st, 0) != 0) #else + if (tree_enter_working_dir(t) != 0) + return NULL; if (stat(tree_current_access_path(t), &t->st) != 0) #endif return NULL; @@ -2138,6 +2415,8 @@ tree_current_lstat(struct tree *t) tree_current_access_path(t), &t->lst, AT_SYMLINK_NOFOLLOW) != 0) #else + if (tree_enter_working_dir(t) != 0) + return NULL; if (lstat(tree_current_access_path(t), &t->lst) != 0) #endif return NULL; @@ -2159,11 +2438,14 @@ tree_current_is_dir(struct tree *t) */ if (t->flags & hasLstat) { /* If lstat() says it's a dir, it must be a dir. */ - if (S_ISDIR(tree_current_lstat(t)->st_mode)) + st = tree_current_lstat(t); + if (st == NULL) + return 0; + if (S_ISDIR(st->st_mode)) return 1; /* Not a dir; might be a link to a dir. */ /* If it's not a link, then it's not a link to a dir. */ - if (!S_ISLNK(tree_current_lstat(t)->st_mode)) + if (!S_ISLNK(st->st_mode)) return 0; /* * It's a link, but we don't know what it's a link to, @@ -2193,9 +2475,13 @@ tree_current_is_physical_dir(struct tree *t) * If stat() says it isn't a dir, then it's not a dir. * If stat() data is cached, this check is free, so do it first. */ - if ((t->flags & hasStat) - && (!S_ISDIR(tree_current_stat(t)->st_mode))) - return 0; + if (t->flags & hasStat) { + st = tree_current_stat(t); + if (st == NULL) + return (0); + if (!S_ISDIR(st->st_mode)) + return (0); + } /* * Either stat() said it was a dir (in which case, we have @@ -2221,7 +2507,8 @@ tree_target_is_same_as_parent(struct tree *t, const struct stat *st) struct tree_entry *te; for (te = t->current->parent; te != NULL; te = te->parent) { - if (te->dev == st->st_dev && te->ino == st->st_ino) + if (te->dev == (int64_t)st->st_dev && + te->ino == (int64_t)st->st_ino) return (1); } return (0); @@ -2238,7 +2525,8 @@ tree_current_is_symblic_link_target(struct tree *t) lst = tree_current_lstat(t); st = tree_current_stat(t); - return (st != NULL && st->st_dev == t->current_filesystem->dev && + return (st != NULL && lst != NULL && + (int64_t)st->st_dev == t->current_filesystem->dev && st->st_dev != lst->st_dev); } diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h index 4446474eb..e5af16b91 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h @@ -34,6 +34,7 @@ #define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED struct tree; +struct archive_entry; struct archive_read_disk { struct archive archive; @@ -55,10 +56,18 @@ struct archive_read_disk { /* Directory traversals. */ struct tree *tree; + int (*open_on_current_dir)(struct tree*, const char *, int); + int (*tree_current_dir_fd)(struct tree*); + int (*tree_enter_working_dir)(struct tree*); /* Set 1 if users request to restore atime . */ int restore_time; - int entry_wd_fd; + /* Set 1 if users request to honor nodump flag . */ + int honor_nodump; + /* Set 1 if users request to enable mac copyfile. */ + int enable_copyfile; + /* Set 1 if users request to traverse mount points. */ + int traverse_mount_points; const char * (*lookup_gname)(void *private, int64_t gid); void (*cleanup_gname)(void *private); @@ -66,6 +75,18 @@ struct archive_read_disk { const char * (*lookup_uname)(void *private, int64_t uid); void (*cleanup_uname)(void *private); void *lookup_uname_data; + + int (*metadata_filter_func)(struct archive *, void *, + struct archive_entry *); + void *metadata_filter_data; + + /* ARCHIVE_MATCH object. */ + struct archive *matching; + /* Callback function, this will be invoked when ARCHIVE_MATCH + * archive_match_*_excluded_ae return true. */ + void (*excluded_cb_func)(struct archive *, void *, + struct archive_entry *); + void *excluded_cb_data; }; #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c index 217a91a86..9c5420d80 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2009 Tim Kientzle - * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,48 +29,13 @@ __FBSDID("$FreeBSD$"); #if defined(_WIN32) && !defined(__CYGWIN__) -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif -#ifdef HAVE_SYS_MOUNT_H -#include <sys/mount.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#ifdef HAVE_SYS_STATVFS_H -#include <sys/statvfs.h> -#endif -#ifdef HAVE_SYS_VFS_H -#include <sys/vfs.h> -#endif -#ifdef HAVE_LINUX_MAGIC_H -#include <linux/magic.h> -#endif -#ifdef HAVE_DIRECT_H -#include <direct.h> -#endif -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif #ifdef HAVE_ERRNO_H #include <errno.h> #endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#if defined(HAVE_WINIOCTL_H) && !defined(__CYGWIN__) #include <winioctl.h> -#endif #include "archive.h" #include "archive_string.h" @@ -86,21 +51,6 @@ __FBSDID("$FreeBSD$"); #define IO_REPARSE_TAG_SYMLINK 0xA000000CL #endif -static BOOL SetFilePointerEx_perso(HANDLE hFile, - LARGE_INTEGER liDistanceToMove, - PLARGE_INTEGER lpNewFilePointer, - DWORD dwMoveMethod) -{ - LARGE_INTEGER li; - li.QuadPart = liDistanceToMove.QuadPart; - li.LowPart = SetFilePointer( - hFile, li.LowPart, &li.HighPart, dwMoveMethod); - if(lpNewFilePointer) { - lpNewFilePointer->QuadPart = li.QuadPart; - } - return li.LowPart != -1 || GetLastError() == NO_ERROR; -} - /*- * This is a new directory-walking system that addresses a number * of problems I've had with fts(3). In particular, it has no @@ -120,11 +70,6 @@ static BOOL SetFilePointerEx_perso(HANDLE hFile, * indicating how to get back to the parent (via chdir("..") for a * regular dir or via fchdir(2) for a symlink). */ -/* - * TODO: - * 1) Loop checking. - * 3) Arbitrary logical traversals by closing/reopening intermediate fds. - */ struct restore_time { const wchar_t *full_path; @@ -153,6 +98,7 @@ struct filesystem { int64_t dev; int synthetic; int remote; + DWORD bytesPerSector; }; /* Definitions for tree_entry.flags bitmap. */ @@ -170,6 +116,11 @@ struct filesystem { * "first visit" is just returned to the client. */ +#define MAX_OVERLAPPED 8 +#define BUFFER_SIZE (1024 * 8) +#define DIRECT_IO 0/* Disabled */ +#define ASYNC_IO 1/* Enabled */ + /* * Local data for this package. */ @@ -177,7 +128,6 @@ struct tree { struct tree_entry *stack; struct tree_entry *current; HANDLE d; -#define INVALID_DIR_HANDLE INVALID_HANDLE_VALUE WIN32_FIND_DATAW _findData; WIN32_FIND_DATAW *findData; int flags; @@ -215,6 +165,7 @@ struct tree { char symlink_mode; struct filesystem *current_filesystem; struct filesystem *filesystem_table; + int initial_filesystem_id; int current_filesystem_id; int max_filesystem_id; int allocated_filesytem; @@ -223,8 +174,24 @@ struct tree { int entry_eof; int64_t entry_remaining_bytes; int64_t entry_total; - unsigned char *entry_buff; - size_t entry_buff_size; + + int ol_idx_doing; + int ol_idx_done; + int ol_num_doing; + int ol_num_done; + int64_t ol_remaining_bytes; + int64_t ol_total; + struct la_overlapped { + OVERLAPPED ol; + struct archive * _a; + unsigned char *buff; + size_t buff_size; + int64_t offset; + size_t bytes_expected; + size_t bytes_transferred; + } ol[MAX_OVERLAPPED]; + int direct_io; + int async_io; }; #define bhfi_dev(bhfi) ((bhfi)->dwVolumeSerialNumber) @@ -242,13 +209,6 @@ struct tree { static int tree_dir_next_windows(struct tree *t, const wchar_t *pattern); -#ifdef HAVE_DIRENT_D_NAMLEN -/* BSD extension; avoids need for a strlen() call. */ -#define D_NAMELEN(dp) (dp)->d_namlen -#else -#define D_NAMELEN(dp) (strlen((dp)->d_name)) -#endif - /* Initiate/terminate a tree traversal. */ static struct tree *tree_open(const wchar_t *, int, int); static struct tree *tree_reopen(struct tree *, const wchar_t *, int); @@ -435,7 +395,8 @@ archive_read_disk_new(void) a->archive.vtable = archive_read_disk_vtable(); a->lookup_uname = trivial_lookup_uname; a->lookup_gname = trivial_lookup_gname; - a->entry_wd_fd = -1; + a->enable_copyfile = 1; + a->traverse_mount_points = 1; return (&a->archive); } @@ -536,6 +497,37 @@ archive_read_disk_set_atime_restored(struct archive *_a) return (ARCHIVE_OK); } +int +archive_read_disk_set_behavior(struct archive *_a, int flags) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + int r = ARCHIVE_OK; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump"); + + if (flags & ARCHIVE_READDISK_RESTORE_ATIME) + r = archive_read_disk_set_atime_restored(_a); + else { + a->restore_time = 0; + if (a->tree != NULL) + a->tree->flags &= ~needsRestoreTimes; + } + if (flags & ARCHIVE_READDISK_HONOR_NODUMP) + a->honor_nodump = 1; + else + a->honor_nodump = 0; + if (flags & ARCHIVE_READDISK_MAC_COPYFILE) + a->enable_copyfile = 1; + else + a->enable_copyfile = 0; + if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) + a->traverse_mount_points = 0; + else + a->traverse_mount_points = 1; + return (r); +} + /* * Trivial implementations of gname/uname lookup functions. * These are normally overridden by the client, but these stub @@ -557,71 +549,92 @@ trivial_lookup_uname(void *private_data, int64_t uid) return (NULL); } +static int64_t +align_num_per_sector(struct tree *t, int64_t size) +{ + int64_t surplus; + + size += t->current_filesystem->bytesPerSector -1; + surplus = size % t->current_filesystem->bytesPerSector; + size -= surplus; + return (size); +} + static int -_archive_read_data_block(struct archive *_a, const void **buff, - size_t *size, int64_t *offset) +start_next_async_read(struct archive_read_disk *a, struct tree *t) { - struct archive_read_disk *a = (struct archive_read_disk *)_a; - struct tree *t = a->tree; - int r; - int64_t bytes; - size_t buffbytes; + struct la_overlapped *olp; + DWORD buffbytes, rbytes; - archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, - "archive_read_data_block"); + if (t->ol_remaining_bytes == 0) + return (ARCHIVE_EOF); - if (t->entry_eof || t->entry_remaining_bytes <= 0) { - r = ARCHIVE_EOF; - goto abort_read_data; - } + olp = &(t->ol[t->ol_idx_doing]); + t->ol_idx_doing = (t->ol_idx_doing + 1) % MAX_OVERLAPPED; /* Allocate read buffer. */ - if (t->entry_buff == NULL) { - t->entry_buff = malloc(1024 * 64); - if (t->entry_buff == NULL) { + if (olp->buff == NULL) { + void *p; + size_t s = (size_t)align_num_per_sector(t, BUFFER_SIZE); + p = VirtualAlloc(NULL, s, MEM_COMMIT, PAGE_READWRITE); + if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory"); - r = ARCHIVE_FATAL; a->archive.state = ARCHIVE_STATE_FATAL; - goto abort_read_data; + return (ARCHIVE_FATAL); } - t->entry_buff_size = 1024 * 64; - } + olp->buff = p; + olp->buff_size = s; + olp->_a = &a->archive; + olp->ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + if (olp->ol.hEvent == NULL) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "CreateEvent failed"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + } else + ResetEvent(olp->ol.hEvent); - buffbytes = t->entry_buff_size; + buffbytes = (DWORD)olp->buff_size; if (buffbytes > t->current_sparse->length) - buffbytes = t->current_sparse->length; + buffbytes = (DWORD)t->current_sparse->length; - /* - * Skip hole. - */ - if (t->current_sparse->offset > t->entry_total) { - LARGE_INTEGER distance; - distance.QuadPart = t->current_sparse->offset; - if (!SetFilePointerEx_perso(t->entry_fh, distance, NULL, FILE_BEGIN)) { - DWORD lasterr; - - lasterr = GetLastError(); - if (lasterr == ERROR_ACCESS_DENIED) - errno = EBADF; - else - la_dosmaperr(lasterr); - archive_set_error(&a->archive, errno, "Seek error"); - r = ARCHIVE_FATAL; - a->archive.state = ARCHIVE_STATE_FATAL; - goto abort_read_data; - } - bytes = t->current_sparse->offset - t->entry_total; - t->entry_remaining_bytes -= bytes; - t->entry_total += bytes; + /* Skip hole. */ + if (t->current_sparse->offset > t->ol_total) { + t->ol_remaining_bytes -= + t->current_sparse->offset - t->ol_total; + } + + olp->offset = t->current_sparse->offset; + olp->ol.Offset = (DWORD)(olp->offset & 0xffffffff); + olp->ol.OffsetHigh = (DWORD)(olp->offset >> 32); + + if (t->ol_remaining_bytes > buffbytes) { + olp->bytes_expected = buffbytes; + t->ol_remaining_bytes -= buffbytes; + } else { + olp->bytes_expected = (size_t)t->ol_remaining_bytes; + t->ol_remaining_bytes = 0; } - if (buffbytes > 0) { - DWORD bytes_read; - if (!ReadFile(t->entry_fh, t->entry_buff, - (uint32_t)buffbytes, &bytes_read, NULL)) { - DWORD lasterr; + olp->bytes_transferred = 0; + t->current_sparse->offset += buffbytes; + t->current_sparse->length -= buffbytes; + t->ol_total = t->current_sparse->offset; + if (t->current_sparse->length == 0 && t->ol_remaining_bytes > 0) + t->current_sparse++; - lasterr = GetLastError(); + if (!ReadFile(t->entry_fh, olp->buff, buffbytes, &rbytes, &(olp->ol))) { + DWORD lasterr; + + lasterr = GetLastError(); + if (lasterr == ERROR_HANDLE_EOF) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Reading file truncated"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } else if (lasterr != ERROR_IO_PENDING) { if (lasterr == ERROR_NO_DATA) errno = EAGAIN; else if (lasterr == ERROR_ACCESS_DENIED) @@ -629,34 +642,96 @@ _archive_read_data_block(struct archive *_a, const void **buff, else la_dosmaperr(lasterr); archive_set_error(&a->archive, errno, "Read error"); - r = ARCHIVE_FATAL; a->archive.state = ARCHIVE_STATE_FATAL; - goto abort_read_data; + return (ARCHIVE_FATAL); } - bytes = bytes_read; } else - bytes = 0; - if (bytes == 0) { - /* Get EOF */ - t->entry_eof = 1; + olp->bytes_transferred = rbytes; + t->ol_num_doing++; + + return (t->ol_remaining_bytes == 0)? ARCHIVE_EOF: ARCHIVE_OK; +} + +static void +cancel_async(struct tree *t) +{ + if (t->ol_num_doing != t->ol_num_done) { + CancelIo(t->entry_fh); + t->ol_num_doing = t->ol_num_done = 0; + } +} + +static int +_archive_read_data_block(struct archive *_a, const void **buff, + size_t *size, int64_t *offset) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t = a->tree; + struct la_overlapped *olp; + DWORD bytes_transferred; + int r = ARCHIVE_FATAL; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + "archive_read_data_block"); + + if (t->entry_eof || t->entry_remaining_bytes <= 0) { r = ARCHIVE_EOF; goto abort_read_data; } - *buff = t->entry_buff; - *size = bytes; - *offset = t->entry_total; - t->entry_total += bytes; - t->entry_remaining_bytes -= bytes; + + /* + * Make a request to read the file in asynchronous. + */ + if (t->ol_num_doing == 0) { + do { + r = start_next_async_read(a, t); + if (r == ARCHIVE_FATAL) + goto abort_read_data; + if (!t->async_io) + break; + } while (r == ARCHIVE_OK && t->ol_num_doing < MAX_OVERLAPPED); + } else { + if (start_next_async_read(a, t) == ARCHIVE_FATAL) + goto abort_read_data; + } + + olp = &(t->ol[t->ol_idx_done]); + t->ol_idx_done = (t->ol_idx_done + 1) % MAX_OVERLAPPED; + if (olp->bytes_transferred) + bytes_transferred = (DWORD)olp->bytes_transferred; + else if (!GetOverlappedResult(t->entry_fh, &(olp->ol), + &bytes_transferred, TRUE)) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, + "GetOverlappedResult failed"); + a->archive.state = ARCHIVE_STATE_FATAL; + r = ARCHIVE_FATAL; + goto abort_read_data; + } + t->ol_num_done++; + + if (bytes_transferred == 0 || + olp->bytes_expected != bytes_transferred) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Reading file truncated"); + a->archive.state = ARCHIVE_STATE_FATAL; + r = ARCHIVE_FATAL; + goto abort_read_data; + } + + *buff = olp->buff; + *size = bytes_transferred; + *offset = olp->offset; + if (olp->offset > t->entry_total) + t->entry_remaining_bytes -= olp->offset - t->entry_total; + t->entry_total = olp->offset + *size; + t->entry_remaining_bytes -= *size; if (t->entry_remaining_bytes == 0) { /* Close the current file descriptor */ close_and_restore_time(t->entry_fh, t, &t->restore_time); t->entry_fh = INVALID_HANDLE_VALUE; t->entry_eof = 1; } - t->current_sparse->offset += bytes; - t->current_sparse->length -= bytes; - if (t->current_sparse->length == 0 && !t->entry_eof) - t->current_sparse++; return (ARCHIVE_OK); abort_read_data: @@ -664,6 +739,7 @@ abort_read_data: *size = 0; *offset = t->entry_total; if (t->entry_fh != INVALID_HANDLE_VALUE) { + cancel_async(t); /* Close the current file descriptor */ close_and_restore_time(t->entry_fh, t, &t->restore_time); t->entry_fh = INVALID_HANDLE_VALUE; @@ -672,26 +748,17 @@ abort_read_data: } static int -_archive_read_next_header2(struct archive *_a, struct archive_entry *entry) +next_entry(struct archive_read_disk *a, struct tree *t, + struct archive_entry *entry) { - struct archive_read_disk *a = (struct archive_read_disk *)_a; - struct tree *t; const BY_HANDLE_FILE_INFORMATION *st; const BY_HANDLE_FILE_INFORMATION *lst; const char*name; int descend, r; - archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, - ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, - "archive_read_next_header2"); - - t = a->tree; - if (t->entry_fh != INVALID_HANDLE_VALUE) { - close_and_restore_time(t->entry_fh, t, &t->restore_time); - t->entry_fh = INVALID_HANDLE_VALUE; - } st = NULL; lst = NULL; + t->descend = 0; do { switch (tree_next(t)) { case TREE_ERROR_FATAL: @@ -701,7 +768,7 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); case TREE_ERROR_DIR: - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, t->tree_errno, "%ls: Couldn't visit directory", tree_current_path(t)); return (ARCHIVE_FAILED); @@ -713,7 +780,7 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) case TREE_REGULAR: lst = tree_current_lstat(t); if (lst == NULL) { - archive_set_error(&a->archive, errno, + archive_set_error(&a->archive, t->tree_errno, "%ls: Cannot stat", tree_current_path(t)); return (ARCHIVE_FAILED); @@ -722,6 +789,26 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) } } while (lst == NULL); + archive_entry_copy_pathname_w(entry, tree_current_path(t)); + + /* + * Perform path matching. + */ + if (a->matching) { + r = archive_match_path_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Faild : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + /* * Distinguish 'L'/'P'/'H' symlink following. */ @@ -759,31 +846,90 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } + if (t->initial_filesystem_id == -1) + t->initial_filesystem_id = t->current_filesystem_id; + if (!a->traverse_mount_points) { + if (t->initial_filesystem_id != t->current_filesystem_id) + return (ARCHIVE_RETRY); + } t->descend = descend; - archive_entry_copy_pathname_w(entry, tree_current_path(t)); - archive_entry_copy_sourcepath_w(entry, tree_current_access_path(t)); tree_archive_entry_copy_bhfi(entry, t, st); - /* Save the times to be restored. */ + /* Save the times to be restored. This must be in before + * calling archive_read_disk_descend() or any chance of it, + * especially, invokng a callback. */ t->restore_time.lastWriteTime = st->ftLastWriteTime; t->restore_time.lastAccessTime = st->ftLastAccessTime; t->restore_time.filetype = archive_entry_filetype(entry); + /* + * Perform time matching. + */ + if (a->matching) { + r = archive_match_time_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Faild : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + /* Lookup uname/gname */ - name = archive_read_disk_uname(_a, archive_entry_uid(entry)); + name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry)); if (name != NULL) archive_entry_copy_uname(entry, name); - name = archive_read_disk_gname(_a, archive_entry_gid(entry)); + name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry)); if (name != NULL) archive_entry_copy_gname(entry, name); + /* + * Perform owner matching. + */ + if (a->matching) { + r = archive_match_owner_excluded(a->matching, entry); + if (r < 0) { + archive_set_error(&(a->archive), errno, + "Faild : %s", archive_error_string(a->matching)); + return (r); + } + if (r) { + if (a->excluded_cb_func) + a->excluded_cb_func(&(a->archive), + a->excluded_cb_data, entry); + return (ARCHIVE_RETRY); + } + } + + /* + * Invoke a meta data filter callback. + */ + if (a->metadata_filter_func) { + if (!a->metadata_filter_func(&(a->archive), + a->metadata_filter_data, entry)) + return (ARCHIVE_RETRY); + } + + archive_entry_copy_sourcepath_w(entry, tree_current_access_path(t)); + r = ARCHIVE_OK; if (archive_entry_filetype(entry) == AE_IFREG && archive_entry_size(entry) > 0) { + DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; + if (t->async_io) + flags |= FILE_FLAG_OVERLAPPED; + if (t->direct_io) + flags |= FILE_FLAG_NO_BUFFERING; + else + flags |= FILE_FLAG_SEQUENTIAL_SCAN; t->entry_fh = CreateFileW(tree_current_access_path(t), - GENERIC_READ, 0, NULL, OPEN_EXISTING, - FILE_FLAG_SEQUENTIAL_SCAN, NULL); + GENERIC_READ, 0, NULL, OPEN_EXISTING, flags, NULL); if (t->entry_fh == INVALID_HANDLE_VALUE) { archive_set_error(&a->archive, errno, "Couldn't open %ls", tree_current_path(a->tree)); @@ -795,6 +941,29 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) (st->dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0) r = setup_sparse_from_disk(a, entry, t->entry_fh); } + return (r); +} + +static int +_archive_read_next_header2(struct archive *_a, struct archive_entry *entry) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t; + int r; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_next_header2"); + + t = a->tree; + if (t->entry_fh != INVALID_HANDLE_VALUE) { + cancel_async(t); + close_and_restore_time(t->entry_fh, t, &t->restore_time); + t->entry_fh = INVALID_HANDLE_VALUE; + } + + while ((r = next_entry(a, t, entry)) == ARCHIVE_RETRY) + archive_entry_clear(entry); /* * EOF and FATAL are persistent at this layer. By @@ -818,6 +987,10 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) t->entry_remaining_bytes = 0; t->entry_eof = 1; } + t->ol_idx_doing = t->ol_idx_done = 0; + t->ol_num_doing = t->ol_num_done = 0; + t->ol_remaining_bytes = t->entry_remaining_bytes; + t->ol_total = 0; a->archive.state = ARCHIVE_STATE_DATA; break; case ARCHIVE_RETRY: @@ -834,7 +1007,7 @@ static int setup_sparse(struct archive_read_disk *a, struct archive_entry *entry) { struct tree *t = a->tree; - int64_t length, offset; + int64_t aligned, length, offset; int i; t->sparse_count = archive_entry_sparse_reset(entry); @@ -851,23 +1024,101 @@ setup_sparse(struct archive_read_disk *a, struct archive_entry *entry) return (ARCHIVE_FATAL); } } + /* + * Get sparse list and make sure those offsets and lengths are + * aligned by a sector size. + */ for (i = 0; i < t->sparse_count; i++) { archive_entry_sparse_next(entry, &offset, &length); - t->sparse_list[i].offset = offset; - t->sparse_list[i].length = length; + aligned = align_num_per_sector(t, offset); + if (aligned != offset) { + aligned -= t->current_filesystem->bytesPerSector; + length += offset - aligned; + } + t->sparse_list[i].offset = aligned; + aligned = align_num_per_sector(t, length); + t->sparse_list[i].length = aligned; } + + aligned = align_num_per_sector(t, archive_entry_size(entry)); if (i == 0) { t->sparse_list[i].offset = 0; - t->sparse_list[i].length = archive_entry_size(entry); + t->sparse_list[i].length = aligned; } else { - t->sparse_list[i].offset = archive_entry_size(entry); + int j, last = i; + + t->sparse_list[i].offset = aligned; t->sparse_list[i].length = 0; + for (i = 0; i < last; i++) { + if ((t->sparse_list[i].offset + + t->sparse_list[i].length) <= + t->sparse_list[i+1].offset) + continue; + /* + * Now sparse_list[i+1] is overlapped by sparse_list[i]. + * Merge those two. + */ + length = t->sparse_list[i+1].offset - + t->sparse_list[i].offset; + t->sparse_list[i+1].offset = t->sparse_list[i].offset; + t->sparse_list[i+1].length += length; + /* Remove sparse_list[i]. */ + for (j = i; j < last; j++) { + t->sparse_list[j].offset = + t->sparse_list[j+1].offset; + t->sparse_list[j].length = + t->sparse_list[j+1].length; + } + last--; + } } t->current_sparse = t->sparse_list; return (ARCHIVE_OK); } +int +archive_read_disk_set_matching(struct archive *_a, struct archive *_ma, + void (*_excluded_func)(struct archive *, void *, struct archive_entry *), + void *_client_data) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_read_disk_set_matching"); + a->matching = _ma; + a->excluded_cb_func = _excluded_func; + a->excluded_cb_data = _client_data; + return (ARCHIVE_OK); +} + +int +archive_read_disk_set_metadata_filter_callback(struct archive *_a, + int (*_metadata_filter_func)(struct archive *, void *, + struct archive_entry *), void *_client_data) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, + "archive_read_disk_set_metadata_filter_callback"); + + a->metadata_filter_func = _metadata_filter_func; + a->metadata_filter_data = _client_data; + return (ARCHIVE_OK); +} + +int +archive_read_disk_can_descend(struct archive *_a) +{ + struct archive_read_disk *a = (struct archive_read_disk *)_a; + struct tree *t = a->tree; + + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_read_disk_can_descend"); + + return (t->visit_type == TREE_REGULAR && t->descend); +} + /* * Called by the client to mark the directory just returned from * tree_next() as needing to be visited. @@ -878,14 +1129,12 @@ archive_read_disk_descend(struct archive *_a) struct archive_read_disk *a = (struct archive_read_disk *)_a; struct tree *t = a->tree; - archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, + archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, "archive_read_disk_descend"); - if (t->visit_type != TREE_REGULAR || !t->descend) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Ignored the request descending the current object"); - return (ARCHIVE_WARN); - } + if (t->visit_type != TREE_REGULAR || !t->descend) + return (ARCHIVE_OK); if (tree_current_is_physical_dir(t)) { tree_push(t, t->basename, t->full_path.s, @@ -920,8 +1169,12 @@ archive_read_disk_open(struct archive *_a, const char *pathname) archive_string_init(&wpath); if (archive_wstring_append_from_mbs(&wpath, pathname, strlen(pathname)) != 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Can't convert a path to a wchar_t string"); + if (errno == ENOMEM) + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't convert a path to a wchar_t string"); a->archive.state = ARCHIVE_STATE_FATAL; ret = ARCHIVE_FATAL; } else @@ -1004,16 +1257,18 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) fid = t->max_filesystem_id++; if (t->max_filesystem_id > t->allocated_filesytem) { size_t s; + void *p; s = t->max_filesystem_id * 2; - t->filesystem_table = realloc(t->filesystem_table, - s * sizeof(*t->filesystem_table)); - if (t->filesystem_table == NULL) { + p = realloc(t->filesystem_table, + s * sizeof(*t->filesystem_table)); + if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate tar data"); return (ARCHIVE_FATAL); } - t->allocated_filesytem = s; + t->filesystem_table = (struct filesystem *)p; + t->allocated_filesytem = (int)s; } t->current_filesystem_id = fid; t->current_filesystem = &(t->filesystem_table[fid]); @@ -1091,6 +1346,7 @@ setup_current_filesystem(struct archive_read_disk *a) if (!GetVolumePathNameW(path, vol, sizeof(vol)/sizeof(vol[0]))) { free(path); t->current_filesystem->remote = -1; + t->current_filesystem->bytesPerSector = 0; archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "GetVolumePathName failed: %d", (int)GetLastError()); return (ARCHIVE_FAILED); @@ -1109,6 +1365,14 @@ setup_current_filesystem(struct archive_read_disk *a) break; } + if (!GetDiskFreeSpaceW(vol, NULL, + &(t->current_filesystem->bytesPerSector), NULL, NULL)) { + t->current_filesystem->bytesPerSector = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "GetDiskFreeSpace failed: %d", (int)GetLastError()); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); } @@ -1249,13 +1513,14 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time) t->depth = 0; t->descend = 0; t->current = NULL; - t->d = INVALID_DIR_HANDLE; + t->d = INVALID_HANDLE_VALUE; t->symlink_mode = t->initial_symlink_mode; archive_string_empty(&(t->full_path)); archive_string_empty(&t->path); t->entry_fh = INVALID_HANDLE_VALUE; t->entry_eof = 0; t->entry_remaining_bytes = 0; + t->initial_filesystem_id = -1; /* Get wchar_t strings from char strings. */ archive_string_init(&ws); @@ -1277,8 +1542,12 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time) /* First item is set up a lot like a symlink traversal. */ /* printf("Looking for wildcard in %s\n", path); */ - /* TODO: wildcard detection here screws up on \\?\c:\ UNC names */ - if (wcschr(base, L'*') || wcschr(base, L'?')) { + if ((base[0] == L'/' && base[1] == L'/' && + base[2] == L'?' && base[3] == L'/' && + (wcschr(base+4, L'*') || wcschr(base+4, L'?'))) || + (!(base[0] == L'/' && base[1] == L'/' && + base[2] == L'?' && base[3] == L'/') && + (wcschr(base, L'*') || wcschr(base, L'?')))) { // It has a wildcard in it... // Separate the last element. p = wcsrchr(base, L'/'); @@ -1298,6 +1567,32 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time) tree_push(t, base, t->full_path.s, 0, 0, 0, NULL); archive_wstring_free(&ws); t->stack->flags = needsFirstVisit; + /* + * Debug flag for Direct IO(No buffering) or Async IO. + * Those dependant on environment variable switches + * will be removed until next release. + */ + { + const char *e; + if ((e = getenv("LIBARCHIVE_DIRECT_IO")) != NULL) { + if (e[0] == '0') + t->direct_io = 0; + else + t->direct_io = 1; + fprintf(stderr, "LIBARCHIVE_DIRECT_IO=%s\n", + (t->direct_io)?"Enabled":"Disabled"); + } else + t->direct_io = DIRECT_IO; + if ((e = getenv("LIBARCHIVE_ASYNC_IO")) != NULL) { + if (e[0] == '0') + t->async_io = 0; + else + t->async_io = 1; + fprintf(stderr, "LIBARCHIVE_ASYNC_IO=%s\n", + (t->async_io)?"Enabled":"Disabled"); + } else + t->async_io = ASYNC_IO; + } return (t); failed: archive_wstring_free(&ws); @@ -1324,7 +1619,7 @@ tree_ascend(struct tree *t) te = t->stack; t->depth--; - close_and_restore_time(INVALID_DIR_HANDLE, t, &te->restore_time); + close_and_restore_time(INVALID_HANDLE_VALUE, t, &te->restore_time); return (0); } @@ -1364,7 +1659,7 @@ tree_next(struct tree *t) while (t->stack != NULL) { /* If there's an open dir, get the next entry from there. */ - if (t->d != INVALID_DIR_HANDLE) { + if (t->d != INVALID_HANDLE_VALUE) { r = tree_dir_next_windows(t, NULL); if (r == 0) continue; @@ -1374,14 +1669,17 @@ tree_next(struct tree *t) if (t->stack->flags & needsFirstVisit) { wchar_t *d = t->stack->name.s; t->stack->flags &= ~needsFirstVisit; - if (wcschr(d, L'*') || wcschr(d, L'?')) { + if (!(d[0] == L'/' && d[1] == L'/' && + d[2] == L'?' && d[3] == L'/') && + (wcschr(d, L'*') || wcschr(d, L'?'))) { r = tree_dir_next_windows(t, d); if (r == 0) continue; return (r); } else { HANDLE h = FindFirstFileW(d, &t->_findData); - if (h == INVALID_DIR_HANDLE) { + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); t->tree_errno = errno; t->visit_type = TREE_ERROR_DIR; return (t->visit_type); @@ -1452,10 +1750,11 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern) archive_wstrcat(&pt, pattern); t->d = FindFirstFileW(pt.s, &t->_findData); archive_wstring_free(&pt); - if (t->d == INVALID_DIR_HANDLE) { + if (t->d == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + t->tree_errno = errno; r = tree_ascend(t); /* Undo "chdir" */ tree_pop(t); - t->tree_errno = errno; t->visit_type = r != 0 ? r : TREE_ERROR_DIR; return (t->visit_type); } @@ -1463,7 +1762,7 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern) pattern = NULL; } else if (!FindNextFileW(t->d, &t->_findData)) { FindClose(t->d); - t->d = INVALID_DIR_HANDLE; + t->d = INVALID_HANDLE_VALUE; t->findData = NULL; return (0); } @@ -1482,7 +1781,7 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern) #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) static void -fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns) +fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns) { ULARGE_INTEGER utc; @@ -1491,11 +1790,11 @@ fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns) if (utc.QuadPart >= EPOC_TIME) { utc.QuadPart -= EPOC_TIME; /* milli seconds base */ - *time = (time_t)(utc.QuadPart / 10000000); + *t = (time_t)(utc.QuadPart / 10000000); /* nano seconds base */ *ns = (long)(utc.QuadPart % 10000000) * 100; } else { - *time = 0; + *t = 0; *ns = 0; } } @@ -1589,8 +1888,11 @@ tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st, flag |= FILE_FLAG_OPEN_REPARSE_POINT; h = CreateFileW(tree_current_access_path(t), 0, 0, NULL, OPEN_EXISTING, flag, NULL); - if (h == INVALID_HANDLE_VALUE) + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + t->tree_errno = errno; return (0); + } r = GetFileInformationByHandle(h, st); CloseHandle(h); return (r); @@ -1709,13 +2011,14 @@ tree_close(struct tree *t) if (t == NULL) return; if (t->entry_fh != INVALID_HANDLE_VALUE) { + cancel_async(t); close_and_restore_time(t->entry_fh, t, &t->restore_time); t->entry_fh = INVALID_HANDLE_VALUE; } /* Close the handle of FindFirstFileW */ - if (t->d != INVALID_DIR_HANDLE) { + if (t->d != INVALID_HANDLE_VALUE) { FindClose(t->d); - t->d = INVALID_DIR_HANDLE; + t->d = INVALID_HANDLE_VALUE; t->findData = NULL; } /* Release anything remaining in the stack. */ @@ -1729,13 +2032,19 @@ tree_close(struct tree *t) static void tree_free(struct tree *t) { + int i; + if (t == NULL) return; archive_wstring_free(&t->path); archive_wstring_free(&t->full_path); free(t->sparse_list); free(t->filesystem_table); - free(t->entry_buff); + for (i = 0; i < MAX_OVERLAPPED; i++) { + if (t->ol[i].buff) + VirtualFree(t->ol[i].buff, 0, MEM_RELEASE); + CloseHandle(t->ol[i].ol.hEvent); + } free(t); } @@ -1775,7 +2084,8 @@ archive_read_disk_entry_from_file(struct archive *_a, h = (HANDLE)_get_osfhandle(fd); r = GetFileInformationByHandle(h, &bhfi); if (r == 0) { - archive_set_error(&a->archive, GetLastError(), + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, "Can't GetFileInformationByHandle"); return (ARCHIVE_FAILED); } @@ -1785,8 +2095,9 @@ archive_read_disk_entry_from_file(struct archive *_a, DWORD flag, desiredAccess; h = FindFirstFileW(path, &findData); - if (h == INVALID_DIR_HANDLE) { - archive_set_error(&a->archive, GetLastError(), + if (h == INVALID_HANDLE_VALUE) { + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, "Can't FindFirstFileW"); return (ARCHIVE_FAILED); } @@ -1807,15 +2118,15 @@ archive_read_disk_entry_from_file(struct archive *_a, h = CreateFileW(path, desiredAccess, 0, NULL, OPEN_EXISTING, flag, NULL); if (h == INVALID_HANDLE_VALUE) { - archive_set_error(&a->archive, - GetLastError(), + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, "Can't CreateFileW"); return (ARCHIVE_FAILED); } r = GetFileInformationByHandle(h, &bhfi); if (r == 0) { - archive_set_error(&a->archive, - GetLastError(), + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, "Can't GetFileInformationByHandle"); CloseHandle(h); return (ARCHIVE_FAILED); @@ -1825,7 +2136,7 @@ archive_read_disk_entry_from_file(struct archive *_a, fileAttributes = bhfi.dwFileAttributes; } else { archive_entry_copy_stat(entry, st); - h = INVALID_DIR_HANDLE; + h = INVALID_HANDLE_VALUE; } /* Lookup uname/gname */ @@ -1854,14 +2165,16 @@ archive_read_disk_entry_from_file(struct archive *_a, h = CreateFileW(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h == INVALID_HANDLE_VALUE) { - archive_set_error(&a->archive, GetLastError(), + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, "Can't CreateFileW"); return (ARCHIVE_FAILED); } } r = GetFileInformationByHandle(h, &bhfi); if (r == 0) { - archive_set_error(&a->archive, GetLastError(), + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, "Can't GetFileInformationByHandle"); if (h != INVALID_HANDLE_VALUE && fd < 0) CloseHandle(h); @@ -1909,7 +2222,7 @@ setup_sparse_from_disk(struct archive_read_disk *a, outranges_size = 2048; outranges = (FILE_ALLOCATED_RANGE_BUFFER *)malloc(outranges_size); if (outranges == NULL) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory"); exit_sts = ARCHIVE_FATAL; goto exit_setup_sparse; @@ -1923,15 +2236,14 @@ setup_sparse_from_disk(struct archive_read_disk *a, ret = DeviceIoControl(handle, FSCTL_QUERY_ALLOCATED_RANGES, &range, sizeof(range), outranges, - outranges_size, &retbytes, NULL); + (DWORD)outranges_size, &retbytes, NULL); if (ret == 0 && GetLastError() == ERROR_MORE_DATA) { free(outranges); outranges_size *= 2; outranges = (FILE_ALLOCATED_RANGE_BUFFER *) malloc(outranges_size); if (outranges == NULL) { - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory"); exit_sts = ARCHIVE_FATAL; goto exit_setup_sparse; @@ -1968,7 +2280,8 @@ setup_sparse_from_disk(struct archive_read_disk *a, } break; } else { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + la_dosmaperr(GetLastError()); + archive_set_error(&a->archive, errno, "DeviceIoControl Failed: %lu", GetLastError()); exit_sts = ARCHIVE_FAILED; goto exit_setup_sparse; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_extract.3 b/Utilities/cmlibarchive/libarchive/archive_read_extract.3 index 882c6e199..6ec0ced93 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_extract.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_extract.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 22, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_READ_EXTRACT 3 .Os .Sh NAME @@ -32,6 +32,8 @@ .Nm archive_read_extract2 , .Nm archive_read_extract_set_progress_callback .Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_read_extract.c b/Utilities/cmlibarchive/libarchive/archive_read_extract.c index aad8ac516..795f2abea 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_extract.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_extract.c @@ -154,7 +154,7 @@ copy_data(struct archive *ar, struct archive *aw) return (ARCHIVE_OK); if (r != ARCHIVE_OK) return (r); - r = archive_write_data_block(aw, buff, size, offset); + r = (int)archive_write_data_block(aw, buff, size, offset); if (r < ARCHIVE_WARN) r = ARCHIVE_WARN; if (r != ARCHIVE_OK) { diff --git a/Utilities/cmlibarchive/libarchive/archive_read_filter.3 b/Utilities/cmlibarchive/libarchive/archive_read_filter.3 index 1cfa21599..8761127d9 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_filter.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_filter.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 19, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_READ_FILTER 3 .Os .Sh NAME @@ -39,6 +39,8 @@ .Nm archive_read_support_filter_program_signature .Nd functions for reading streaming archives .\" +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_read_format.3 b/Utilities/cmlibarchive/libarchive/archive_read_format.3 index e707e05f6..53b9a7e0e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_format.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_format.3 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $ +.\" $FreeBSD$ .\" -.Dd March 19, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_READ_FORMAT 3 .Os .Sh NAME @@ -45,6 +45,8 @@ .Nm archive_read_support_format_zip .Nd functions for reading streaming archives .\" +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_read_free.3 b/Utilities/cmlibarchive/libarchive/archive_read_free.3 index f5f2515a8..5b218225b 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_free.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_free.3 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $ +.\" $FreeBSD$ .\" -.Dd March 20, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_READ_FREE 3 .Os .Sh NAME @@ -32,6 +32,8 @@ .Nm archive_read_finish , .Nm archive_read_free .Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_read_header.3 b/Utilities/cmlibarchive/libarchive/archive_read_header.3 index 999e963cf..480a666ca 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_header.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_header.3 @@ -24,13 +24,15 @@ .\" .\" $FreeBSD$ .\" -.Dd March 22, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_READ_HEADER 3 .Os .Sh NAME .Nm archive_read_next_header , .Nm archive_read_next_header2 .Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_read_new.3 b/Utilities/cmlibarchive/libarchive/archive_read_new.3 index e04406aa6..0c9d1a7fb 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_new.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_new.3 @@ -22,14 +22,16 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $ +.\" $FreeBSD$ .\" -.Dd March 20, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_READ_NEW 3 .Os .Sh NAME .Nm archive_read_new .Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft struct archive * diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open.3 b/Utilities/cmlibarchive/libarchive/archive_read_open.3 index 09c057568..30a740bef 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_open.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_open.3 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $ +.\" $FreeBSD$ .\" -.Dd March 19, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_READ_OPEN 3 .Os .Sh NAME @@ -35,6 +35,8 @@ .Nm archive_read_open_filename , .Nm archive_read_open_memory , .Nd functions for reading streaming archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_fd.c b/Utilities/cmlibarchive/libarchive/archive_read_open_fd.c index d8f657295..e0f95bf41 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_open_fd.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_open_fd.c @@ -119,7 +119,8 @@ file_read(struct archive *a, void *client_data, const void **buff) if (bytes_read < 0) { if (errno == EINTR) continue; - archive_set_error(a, errno, "Error reading fd %d", mine->fd); + archive_set_error(a, errno, "Error reading fd %d", + mine->fd); } return (bytes_read); } @@ -129,8 +130,8 @@ static int64_t file_skip(struct archive *a, void *client_data, int64_t request) { struct read_fd_data *mine = (struct read_fd_data *)client_data; - off_t skip = (off_t)request; - off_t old_offset, new_offset; + int64_t skip = request; + int64_t old_offset, new_offset; int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */ if (!mine->use_lseek) diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_file.c b/Utilities/cmlibarchive/libarchive/archive_read_open_file.c index b1aac0a7c..3a33c258e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_open_file.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_open_file.c @@ -108,11 +108,11 @@ static ssize_t file_read(struct archive *a, void *client_data, const void **buff) { struct read_FILE_data *mine = (struct read_FILE_data *)client_data; - ssize_t bytes_read; + size_t bytes_read; *buff = mine->buffer; bytes_read = fread(mine->buffer, 1, mine->block_size, mine->f); - if (bytes_read < 0) { + if (bytes_read < mine->block_size && ferror(mine->f)) { archive_set_error(a, errno, "Error reading file"); } return (bytes_read); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c index bf5269724..622c960c4 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c @@ -60,11 +60,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_filename.c 201093 2009 #endif #include "archive.h" +#include "archive_private.h" #include "archive_string.h" #ifndef O_BINARY #define O_BINARY 0 #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif struct read_file_data { int fd; @@ -79,9 +83,10 @@ struct read_file_data { } filename; /* Must be last! */ }; +static int file_open(struct archive *, void *); static int file_close(struct archive *, void *); -static int file_open_filename(struct archive *, enum fnt_e, const void *, - size_t); +static int file_close2(struct archive *, void *); +static int file_switch(struct archive *, void *, void *); static ssize_t file_read(struct archive *, void *, const void **buff); static int64_t file_seek(struct archive *, void *, int64_t request, int); static int64_t file_skip(struct archive *, void *, int64_t request); @@ -98,26 +103,78 @@ int archive_read_open_filename(struct archive *a, const char *filename, size_t block_size) { - enum fnt_e filename_type; + const char *filenames[2]; + filenames[0] = filename; + filenames[1] = NULL; + return archive_read_open_filenames(a, filenames, block_size); +} + +int +archive_read_open_filenames(struct archive *a, const char **filenames, + size_t block_size) +{ + struct read_file_data *mine; + const char *filename = NULL; + if (filenames) + filename = *(filenames++); + + archive_clear_error(a); + do + { + if (filename == NULL) + filename = ""; + mine = (struct read_file_data *)calloc(1, + sizeof(*mine) + strlen(filename)); + if (mine == NULL) + goto no_memory; + strcpy(mine->filename.m, filename); + mine->block_size = block_size; + mine->fd = -1; + mine->buffer = NULL; + mine->st_mode = mine->use_lseek = 0; + if (filename == NULL || filename[0] == '\0') { + mine->filename_type = FNT_STDIN; + } else + mine->filename_type = FNT_MBS; + if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) + return (ARCHIVE_FATAL); + if (filenames == NULL) + break; + filename = *(filenames++); + } while (filename != NULL && filename[0] != '\0'); + archive_read_set_open_callback(a, file_open); + archive_read_set_read_callback(a, file_read); + archive_read_set_skip_callback(a, file_skip); + archive_read_set_close_callback(a, file_close); + archive_read_set_switch_callback(a, file_switch); + archive_read_set_seek_callback(a, file_seek); - if (filename == NULL || filename[0] == '\0') { - filename_type = FNT_STDIN; - } else - filename_type = FNT_MBS; - return (file_open_filename(a, filename_type, filename, block_size)); + return (archive_read_open1(a)); +no_memory: + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); } int archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename, size_t block_size) { - enum fnt_e filename_type; + struct read_file_data *mine = (struct read_file_data *)calloc(1, + sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t)); + if (!mine) + { + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + mine->fd = -1; + mine->block_size = block_size; if (wfilename == NULL || wfilename[0] == L'\0') { - filename_type = FNT_STDIN; + mine->filename_type = FNT_STDIN; } else { #if defined(_WIN32) && !defined(__CYGWIN__) - filename_type = FNT_WCS; + mine->filename_type = FNT_WCS; + wcscpy(mine->filename.w, wfilename); #else /* * POSIX system does not support a wchar_t interface for @@ -125,31 +182,43 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename, * filename to multi-byte one and use it. */ struct archive_string fn; - int r; archive_string_init(&fn); if (archive_string_append_from_wcs(&fn, wfilename, wcslen(wfilename)) != 0) { - archive_set_error(a, EINVAL, - "Failed to convert a wide-character filename to" - " a multi-byte filename"); + if (errno == ENOMEM) + archive_set_error(a, errno, + "Can't allocate memory"); + else + archive_set_error(a, EINVAL, + "Failed to convert a wide-character" + " filename to a multi-byte filename"); archive_string_free(&fn); + free(mine); return (ARCHIVE_FATAL); } - r = file_open_filename(a, FNT_MBS, fn.s, block_size); + mine->filename_type = FNT_MBS; + strcpy(mine->filename.m, fn.s); archive_string_free(&fn); - return (r); #endif } - return (file_open_filename(a, filename_type, wfilename, block_size)); + if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) + return (ARCHIVE_FATAL); + archive_read_set_open_callback(a, file_open); + archive_read_set_read_callback(a, file_read); + archive_read_set_skip_callback(a, file_skip); + archive_read_set_close_callback(a, file_close); + archive_read_set_switch_callback(a, file_switch); + archive_read_set_seek_callback(a, file_seek); + + return (archive_read_open1(a)); } static int -file_open_filename(struct archive *a, enum fnt_e filename_type, - const void *_filename, size_t block_size) +file_open(struct archive *a, void *client_data) { struct stat st; - struct read_file_data *mine; + struct read_file_data *mine = (struct read_file_data *)client_data; void *buffer; const char *filename = NULL; const wchar_t *wfilename = NULL; @@ -164,7 +233,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type, #endif archive_clear_error(a); - if (filename_type == FNT_STDIN) { + if (mine->filename_type == FNT_STDIN) { /* We used to delegate stdin support by * directly calling archive_read_open_fd(a,0,block_size) * here, but that doesn't (and shouldn't) handle the @@ -179,9 +248,10 @@ file_open_filename(struct archive *a, enum fnt_e filename_type, setmode(0, O_BINARY); #endif filename = ""; - } else if (filename_type == FNT_MBS) { - filename = (const char *)_filename; - fd = open(filename, O_RDONLY | O_BINARY); + } else if (mine->filename_type == FNT_MBS) { + filename = mine->filename.m; + fd = open(filename, O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); if (fd < 0) { archive_set_error(a, errno, "Failed to open '%s'", filename); @@ -189,7 +259,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type, } } else { #if defined(_WIN32) && !defined(__CYGWIN__) - wfilename = (const wchar_t *)_filename; + wfilename = mine->filename.w; fd = _wopen(wfilename, O_RDONLY | O_BINARY); if (fd < 0 && errno == ENOENT) { wchar_t *fullpath; @@ -211,7 +281,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type, #endif } if (fstat(fd, &st) != 0) { - if (filename_type == FNT_WCS) + if (mine->filename_type == FNT_WCS) archive_set_error(a, errno, "Can't stat '%S'", wfilename); else @@ -276,50 +346,32 @@ file_open_filename(struct archive *a, enum fnt_e filename_type, #endif /* TODO: Add an "is_tape_like" variable and appropriate tests. */ - if (filename_type == FNT_WCS) - mine = (struct read_file_data *)calloc(1, - sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t)); - else - mine = (struct read_file_data *)calloc(1, - sizeof(*mine) + strlen(filename)); /* Disk-like devices prefer power-of-two block sizes. */ /* Use provided block_size as a guide so users have some control. */ if (is_disk_like) { size_t new_block_size = 64 * 1024; - while (new_block_size < block_size + while (new_block_size < mine->block_size && new_block_size < 64 * 1024 * 1024) new_block_size *= 2; - block_size = new_block_size; + mine->block_size = new_block_size; } - buffer = malloc(block_size); + buffer = malloc(mine->block_size); if (mine == NULL || buffer == NULL) { archive_set_error(a, ENOMEM, "No memory"); free(mine); free(buffer); return (ARCHIVE_FATAL); } - if (filename_type == FNT_WCS) - wcscpy(mine->filename.w, wfilename); - else - strcpy(mine->filename.m, filename); - mine->filename_type = filename_type; - mine->block_size = block_size; mine->buffer = buffer; mine->fd = fd; /* Remember mode so close can decide whether to flush. */ mine->st_mode = st.st_mode; /* Disk-like inputs can use lseek(). */ - if (is_disk_like) { - archive_read_set_seek_callback(a, file_seek); + if (is_disk_like) mine->use_lseek = 1; - } - archive_read_set_read_callback(a, file_read); - archive_read_set_skip_callback(a, file_skip); - archive_read_set_close_callback(a, file_close); - archive_read_set_callback_data(a, mine); - return (archive_read_open1(a)); + return (ARCHIVE_OK); } static ssize_t @@ -397,9 +449,7 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request) /* TODO: Deal with case where off_t isn't 64 bits. * This shouldn't be a problem on Linux or other POSIX * systems, since the configuration logic for libarchive - * tries to obtain a 64-bit off_t. It's still an issue - * on Windows, though, so it might suffice to just use - * _lseeki64() on Windows. + * tries to obtain a 64-bit off_t. */ if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 && (new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0) @@ -450,7 +500,7 @@ static int64_t file_seek(struct archive *a, void *client_data, int64_t request, int whence) { struct read_file_data *mine = (struct read_file_data *)client_data; - off_t r; + int64_t r; /* We use off_t here because lseek() is declared that way. */ /* See above for notes about when off_t is less than 64 bits. */ @@ -471,7 +521,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence) } static int -file_close(struct archive *a, void *client_data) +file_close2(struct archive *a, void *client_data) { struct read_file_data *mine = (struct read_file_data *)client_data; @@ -504,6 +554,23 @@ file_close(struct archive *a, void *client_data) close(mine->fd); } free(mine->buffer); + mine->buffer = NULL; + mine->fd = -1; + return (ARCHIVE_OK); +} + +static int +file_close(struct archive *a, void *client_data) +{ + struct read_file_data *mine = (struct read_file_data *)client_data; + file_close2(a, client_data); free(mine); return (ARCHIVE_OK); } + +static int +file_switch(struct archive *a, void *client_data1, void *client_data2) +{ + file_close2(a, client_data1); + return file_open(a, client_data2); +} diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c b/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c index 07940a2ac..bcc7d6f78 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c @@ -149,6 +149,7 @@ memory_read_seek(struct archive *a, void *client_data, int64_t offset, int whenc { struct read_memory_data *mine = (struct read_memory_data *)client_data; + (void)a; /* UNUSED */ switch (whence) { case SEEK_SET: mine->p = mine->start + offset; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_private.h b/Utilities/cmlibarchive/libarchive/archive_read_private.h index 76d0b91d9..8a6c859a8 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_read_private.h @@ -58,6 +58,8 @@ struct archive_read_filter; struct archive_read_filter_bidder { /* Configuration data for the bidder. */ void *data; + /* Name of the filter */ + const char *name; /* Taste the upstream filter to see if we handle this. */ int (*bid)(struct archive_read_filter_bidder *, struct archive_read_filter *); @@ -82,6 +84,8 @@ struct archive_read_filter { struct archive_read_filter_bidder *bidder; /* My bidder. */ struct archive_read_filter *upstream; /* Who I read from. */ struct archive_read *archive; /* Associated archive. */ + /* Open a block for reading */ + int (*open)(struct archive_read_filter *self); /* Return next block. */ ssize_t (*read)(struct archive_read_filter *, const void **); /* Skip forward this many bytes. */ @@ -90,6 +94,8 @@ struct archive_read_filter { int64_t (*seek)(struct archive_read_filter *self, int64_t offset, int whence); /* Close (just this filter) and free(self). */ int (*close)(struct archive_read_filter *self); + /* Function that handles switching from reading one block to the next/prev */ + int (*sswitch)(struct archive_read_filter *self, unsigned int iindex); /* My private data. */ void *data; @@ -118,13 +124,22 @@ struct archive_read_filter { * transformation filters. This will probably break the API/ABI and * so should be deferred at least until libarchive 3.0. */ +struct archive_read_data_node { + int64_t begin_position; + int64_t total_size; + void *data; +}; struct archive_read_client { archive_open_callback *opener; archive_read_callback *reader; archive_skip_callback *skipper; archive_seek_callback *seeker; archive_close_callback *closer; - void *data; + archive_switch_callback *switcher; + unsigned int nodes; + unsigned int cursor; + int64_t position; + struct archive_read_data_node *dataset; }; struct archive_read { @@ -134,8 +149,8 @@ struct archive_read { /* Dev/ino of the archive being read/written. */ int skip_file_set; - dev_t skip_file_dev; - ino_t skip_file_ino; + int64_t skip_file_dev; + int64_t skip_file_ino; /* * Used by archive_read_data() to track blocks and copy @@ -146,18 +161,33 @@ struct archive_read { int64_t read_data_output_offset; size_t read_data_remaining; - /* Callbacks to open/read/write/close client archive stream. */ + /* + * Used by formats/filters to determine the amount of data + * requested from a call to archive_read_data(). This is only + * useful when the format/filter has seek support. + */ + char read_data_is_posix_read; + size_t read_data_requested; + + /* Callbacks to open/read/write/close client archive streams. */ struct archive_read_client client; /* Registered filter bidders. */ - struct archive_read_filter_bidder bidders[9]; + struct archive_read_filter_bidder bidders[14]; /* Last filter in chain */ struct archive_read_filter *filter; + /* Whether to bypass filter bidding process */ + int bypass_filter_bidding; + /* File offset of beginning of most recently-read header. */ int64_t header_position; + /* Nodes and offsets of compressed data block */ + unsigned int data_start_node; + unsigned int data_end_node; + /* * Format detection is mostly the same as compression * detection, with one significant difference: The bidders @@ -175,6 +205,7 @@ struct archive_read { int (*read_header)(struct archive_read *, struct archive_entry *); int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *); int (*read_data_skip)(struct archive_read *); + int64_t (*seek_data)(struct archive_read *, int64_t, int); int (*cleanup)(struct archive_read *); } formats[16]; struct archive_format_descriptor *format; /* Active format. */ @@ -194,6 +225,7 @@ int __archive_read_register_format(struct archive_read *a, int (*read_header)(struct archive_read *, struct archive_entry *), int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *), int (*read_data_skip)(struct archive_read *), + int64_t (*seek_data)(struct archive_read *, int64_t, int), int (*cleanup)(struct archive_read *)); int __archive_read_get_bidder(struct archive_read *a, @@ -207,4 +239,6 @@ int64_t __archive_read_filter_seek(struct archive_read_filter *, int64_t, int); int64_t __archive_read_consume(struct archive_read *, int64_t); int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t); int __archive_read_program(struct archive_read_filter *, const char *); +void __archive_read_free_filters(struct archive_read *); +int __archive_read_close_filters(struct archive_read *); #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_read_set_format.c b/Utilities/cmlibarchive/libarchive/archive_read_set_format.c new file mode 100644 index 000000000..190f4369d --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_read_set_format.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 2003-2012 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +int +archive_read_set_format(struct archive *_a, int code) +{ + int r1, r2, slots, i; + char str[10]; + struct archive_read *a = (struct archive_read *)_a; + + if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK)) + return r1; + + r1 = r2 = (ARCHIVE_OK); + if (a->format) + r2 = (ARCHIVE_WARN); + switch (code & ARCHIVE_FORMAT_BASE_MASK) + { + case ARCHIVE_FORMAT_7ZIP: + strcpy(str, "7zip"); + break; + case ARCHIVE_FORMAT_AR: + strcpy(str, "ar"); + break; + case ARCHIVE_FORMAT_CAB: + strcpy(str, "cab"); + break; + case ARCHIVE_FORMAT_CPIO: + strcpy(str, "cpio"); + break; + case ARCHIVE_FORMAT_ISO9660: + strcpy(str, "iso9660"); + break; + case ARCHIVE_FORMAT_LHA: + strcpy(str, "lha"); + break; + case ARCHIVE_FORMAT_MTREE: + strcpy(str, "mtree"); + break; + case ARCHIVE_FORMAT_RAR: + strcpy(str, "rar"); + break; + case ARCHIVE_FORMAT_TAR: + strcpy(str, "tar"); + break; + case ARCHIVE_FORMAT_XAR: + strcpy(str, "xar"); + break; + case ARCHIVE_FORMAT_ZIP: + strcpy(str, "zip"); + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Invalid format code specified"); + return (ARCHIVE_FATAL); + } + + slots = sizeof(a->formats) / sizeof(a->formats[0]); + a->format = &(a->formats[0]); + for (i = 0; i < slots; i++, a->format++) { + if (!a->format->name || !strcmp(a->format->name, str)) + break; + } + if (!a->format->name || strcmp(a->format->name, str)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "Internal error: Unable to set format"); + r1 = (ARCHIVE_FATAL); + } + + return (r1 < r2) ? r1 : r2; +} diff --git a/Utilities/cmlibarchive/libarchive/archive_read_set_options.3 b/Utilities/cmlibarchive/libarchive/archive_read_set_options.3 index 81efb08b5..6fe9f90f8 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_set_options.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_set_options.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 13, 2009 +.Dd February 2, 2012 .Dt ARCHIVE_READ_OPTIONS 3 .Os .Sh NAME @@ -34,6 +34,8 @@ .Nm archive_read_set_options .Nd functions controlling options for reading archives .\" +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .Ft int .Fo archive_read_set_filter_option diff --git a/Utilities/cmlibarchive/libarchive/archive_read_set_options.c b/Utilities/cmlibarchive/libarchive/archive_read_set_options.c index d6a5f45cc..793f8f73e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_set_options.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_set_options.c @@ -78,7 +78,7 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o, struct archive_read *a = (struct archive_read *)_a; struct archive_format_descriptor *format; size_t i; - int r, rv = ARCHIVE_FAILED; + int r, rv = ARCHIVE_WARN; for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) { format = &a->formats[i]; @@ -102,6 +102,10 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o, if (r == ARCHIVE_OK) rv = ARCHIVE_OK; } + /* If the format name didn't match, return a special code for + * _archive_set_option[s]. */ + if (rv == ARCHIVE_WARN && m != NULL) + rv = ARCHIVE_WARN - 1; return (rv); } @@ -112,7 +116,7 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o, struct archive_read *a = (struct archive_read *)_a; struct archive_read_filter *filter; struct archive_read_filter_bidder *bidder; - int r, rv = ARCHIVE_FAILED; + int r, rv = ARCHIVE_WARN; for (filter = a->filter; filter != NULL; filter = filter->upstream) { bidder = filter->bidder; @@ -135,6 +139,10 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o, if (r == ARCHIVE_OK) rv = ARCHIVE_OK; } + /* If the filter name didn't match, return a special code for + * _archive_set_option[s]. */ + if (rv == ARCHIVE_WARN && m != NULL) + rv = ARCHIVE_WARN - 1; return (rv); } diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c index 733d86298..b778cfb79 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c @@ -48,7 +48,7 @@ archive_read_support_filter_all(struct archive *a) archive_read_support_filter_bzip2(a); /* The decompress code doesn't use an outside library. */ archive_read_support_filter_compress(a); - /* Gzip decompress falls back to "gunzip" command-line. */ + /* Gzip decompress falls back to "gzip -d" command-line. */ archive_read_support_filter_gzip(a); /* Lzip falls back to "unlzip" command-line program. */ archive_read_support_filter_lzip(a); @@ -63,6 +63,12 @@ archive_read_support_filter_all(struct archive *a) archive_read_support_filter_uu(a); /* The decode code doesn't use an outside library. */ archive_read_support_filter_rpm(a); + /* The decode code always uses "lrzip -q -d" command-line. */ + archive_read_support_filter_lrzip(a); + /* Lzop decompress falls back to "lzop -d" command-line. */ + archive_read_support_filter_lzop(a); + /* The decode code always uses "grzip -d" command-line. */ + archive_read_support_filter_grzip(a); /* Note: We always return ARCHIVE_OK here, even if some of the * above return ARCHIVE_WARN. The intent here is to enable diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_bzip2.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_bzip2.c index af618b09a..2b1a5e2aa 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_bzip2.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_bzip2.c @@ -94,6 +94,7 @@ archive_read_support_filter_bzip2(struct archive *_a) return (ARCHIVE_FATAL); reader->data = NULL; + reader->name = "bzip2"; reader->bid = bzip2_reader_bid; reader->init = bzip2_reader_init; reader->options = NULL; @@ -102,7 +103,7 @@ archive_read_support_filter_bzip2(struct archive *_a) return (ARCHIVE_OK); #else archive_set_error(_a, ARCHIVE_ERRNO_MISC, - "Using external bunzip2 program"); + "Using external bzip2 program"); return (ARCHIVE_WARN); #endif } @@ -170,11 +171,11 @@ bzip2_reader_init(struct archive_read_filter *self) { int r; - r = __archive_read_program(self, "bunzip2"); + r = __archive_read_program(self, "bzip2 -d"); /* Note: We set the format here even if __archive_read_program() * above fails. We do, after all, know what the format is * even if we weren't able to read it. */ - self->code = ARCHIVE_COMPRESSION_BZIP2; + self->code = ARCHIVE_FILTER_BZIP2; self->name = "bzip2"; return (r); } @@ -192,7 +193,7 @@ bzip2_reader_init(struct archive_read_filter *self) void *out_block; struct private_data *state; - self->code = ARCHIVE_COMPRESSION_BZIP2; + self->code = ARCHIVE_FILTER_BZIP2; self->name = "bzip2"; state = (struct private_data *)calloc(sizeof(*state), 1); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c index 1b8530004..3f5d1f37e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c @@ -163,6 +163,7 @@ archive_read_support_filter_compress(struct archive *_a) return (ARCHIVE_FATAL); bidder->data = NULL; + bidder->name = "compress (.Z)"; bidder->bid = compress_bidder_bid; bidder->init = compress_bidder_init; bidder->options = NULL; @@ -212,7 +213,7 @@ compress_bidder_init(struct archive_read_filter *self) void *out_block; int code; - self->code = ARCHIVE_COMPRESSION_COMPRESS; + self->code = ARCHIVE_FILTER_COMPRESS; self->name = "compress (.Z)"; state = (struct private_data *)calloc(sizeof(*state), 1); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_grzip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_grzip.c new file mode 100644 index 000000000..84c86aeb4 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_grzip.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +static const unsigned char grzip_magic[] = { + 0x47, 0x52, 0x5a, 0x69, 0x70, 0x49, 0x49, 0x00, + 0x02, 0x04, 0x3a, 0x29 }; + +static int grzip_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int grzip_bidder_init(struct archive_read_filter *); + + +static int +grzip_reader_free(struct archive_read_filter_bidder *self) +{ + (void)self; /* UNUSED */ + return (ARCHIVE_OK); +} + +int +archive_read_support_filter_grzip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *reader; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_grzip"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->bid = grzip_bidder_bid; + reader->init = grzip_bidder_init; + reader->options = NULL; + reader->free = grzip_reader_free; + /* This filter always uses an external program. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external grzip program for grzip decompression"); + return (ARCHIVE_WARN); +} + +/* + * Bidder just verifies the header and returns the number of verified bits. + */ +static int +grzip_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *p; + ssize_t avail; + + (void)self; /* UNUSED */ + + p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), &avail); + if (p == NULL || avail == 0) + return (0); + + if (memcmp(p, grzip_magic, sizeof(grzip_magic))) + return (0); + + return (sizeof(grzip_magic) * 8); +} + +static int +grzip_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "grzip -d"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_GRZIP; + self->name = "grzip"; + return (r); +} diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_gzip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_gzip.c index 9d03b2b2c..e9f59f13f 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_gzip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_gzip.c @@ -72,7 +72,7 @@ static int gzip_filter_close(struct archive_read_filter *); * * TODO: If zlib is unavailable, gzip_bidder_init() should * use the compress_program framework to try to fire up an external - * gunzip program. + * gzip program. */ static int gzip_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); @@ -100,6 +100,7 @@ archive_read_support_filter_gzip(struct archive *_a) return (ARCHIVE_FATAL); bidder->data = NULL; + bidder->name = "gzip"; bidder->bid = gzip_bidder_bid; bidder->init = gzip_bidder_init; bidder->options = NULL; @@ -109,7 +110,7 @@ archive_read_support_filter_gzip(struct archive *_a) return (ARCHIVE_OK); #else archive_set_error(_a, ARCHIVE_ERRNO_MISC, - "Using external gunzip program"); + "Using external gzip program"); return (ARCHIVE_WARN); #endif } @@ -121,7 +122,7 @@ archive_read_support_filter_gzip(struct archive *_a) * number of bytes in header. If pbits is non-NULL, it receives a * count of bits verified, suitable for use by bidder. */ -static int +static ssize_t peek_at_header(struct archive_read_filter *filter, int *pbits) { const unsigned char *p; @@ -223,7 +224,7 @@ gzip_bidder_bid(struct archive_read_filter_bidder *self, /* * If we don't have the library on this system, we can't do the - * decompression directly. We can, however, try to run gunzip + * decompression directly. We can, however, try to run "gzip -d" * in case that's available. */ static int @@ -231,11 +232,11 @@ gzip_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_program(self, "gunzip"); + r = __archive_read_program(self, "gzip -d"); /* Note: We set the format here even if __archive_read_program() * above fails. We do, after all, know what the format is * even if we weren't able to read it. */ - self->code = ARCHIVE_COMPRESSION_GZIP; + self->code = ARCHIVE_FILTER_GZIP; self->name = "gzip"; return (r); } @@ -252,7 +253,7 @@ gzip_bidder_init(struct archive_read_filter *self) static const size_t out_block_size = 64 * 1024; void *out_block; - self->code = ARCHIVE_COMPRESSION_GZIP; + self->code = ARCHIVE_FILTER_GZIP; self->name = "gzip"; state = (struct private_data *)calloc(sizeof(*state), 1); @@ -299,7 +300,7 @@ consume_header(struct archive_read_filter *self) /* Initialize compression library. */ state->stream.next_in = (unsigned char *)(uintptr_t) __archive_read_filter_ahead(self->upstream, 1, &avail); - state->stream.avail_in = avail; + state->stream.avail_in = (uInt)avail; ret = inflateInit2(&(state->stream), -15 /* Don't check for zlib header */); @@ -380,7 +381,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p) /* Empty our output buffer. */ state->stream.next_out = state->out_block; - state->stream.avail_out = state->out_block_size; + state->stream.avail_out = (uInt)state->out_block_size; /* Try to fill the output buffer. */ while (state->stream.avail_out > 0 && !state->eof) { @@ -407,7 +408,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p) "truncated gzip input"); return (ARCHIVE_FATAL); } - state->stream.avail_in = avail_in; + state->stream.avail_in = (uInt)avail_in; /* Decompress and consume some of that data. */ ret = inflate(&(state->stream), 0); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lrzip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lrzip.c new file mode 100644 index 000000000..c82a8e2f1 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lrzip.c @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#define LRZIP_HEADER_MAGIC "LRZI" +#define LRZIP_HEADER_MAGIC_LEN 4 + +static int lrzip_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int lrzip_bidder_init(struct archive_read_filter *); + + +static int +lrzip_reader_free(struct archive_read_filter_bidder *self) +{ + (void)self; /* UNUSED */ + return (ARCHIVE_OK); +} + +int +archive_read_support_filter_lrzip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *reader; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_lrzip"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->name = "lrzip"; + reader->bid = lrzip_bidder_bid; + reader->init = lrzip_bidder_init; + reader->options = NULL; + reader->free = lrzip_reader_free; + /* This filter always uses an external program. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lrzip program for lrzip decompression"); + return (ARCHIVE_WARN); +} + +/* + * Bidder just verifies the header and returns the number of verified bits. + */ +static int +lrzip_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *p; + ssize_t avail, len; + int i; + + (void)self; /* UNUSED */ + /* Start by looking at the first six bytes of the header, which + * is all fixed layout. */ + len = 6; + p = __archive_read_filter_ahead(filter, len, &avail); + if (p == NULL || avail == 0) + return (0); + + if (memcmp(p, LRZIP_HEADER_MAGIC, LRZIP_HEADER_MAGIC_LEN)) + return (0); + + /* current major version is always 0, verify this */ + if (p[LRZIP_HEADER_MAGIC_LEN]) + return 0; + /* support only v0.6+ lrzip for sanity */ + i = p[LRZIP_HEADER_MAGIC_LEN + 1]; + if ((i < 6) || (i > 10)) + return 0; + + return (int)len; +} + +static int +lrzip_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "lrzip -d -q"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_LRZIP; + self->name = "lrzip"; + return (r); +} diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c new file mode 100644 index 000000000..7958fa50a --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c @@ -0,0 +1,486 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_LZO_LZOCONF_H +#include <lzo/lzoconf.h> +#endif +#ifdef HAVE_LZO_LZO1X_H +#include <lzo/lzo1x.h> +#endif +#ifdef HAVE_ZLIB_H +#include <cm_zlib.h> /* for crc32 and adler32 */ +#endif + +#include "archive.h" +#if !defined(HAVE_ZLIB_H) &&\ + defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +#include "archive_crc32.h" +#endif +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#ifndef HAVE_ZLIB_H +#define adler32 lzo_adler32 +#endif + +#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" +#define LZOP_HEADER_MAGIC_LEN 9 + +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +struct read_lzop { + unsigned char *out_block; + size_t out_block_size; + int64_t total_out; + int flags; + uint32_t compressed_cksum; + uint32_t uncompressed_cksum; + size_t compressed_size; + size_t uncompressed_size; + size_t unconsumed_bytes; + char in_stream; + char eof; /* True = found end of compressed data. */ +}; + +#define FILTER 0x0800 +#define CRC32_HEADER 0x1000 +#define EXTRA_FIELD 0x0040 +#define ADLER32_UNCOMPRESSED 0x0001 +#define ADLER32_COMPRESSED 0x0002 +#define CRC32_UNCOMPRESSED 0x0100 +#define CRC32_COMPRESSED 0x0200 +#define MAX_BLOCK_SIZE (64 * 1024 * 1024) + +static ssize_t lzop_filter_read(struct archive_read_filter *, const void **); +static int lzop_filter_close(struct archive_read_filter *); +#endif + +static int lzop_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int lzop_bidder_init(struct archive_read_filter *); + +int +archive_read_support_filter_lzop(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *reader; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_lzop"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->bid = lzop_bidder_bid; + reader->init = lzop_bidder_init; + reader->options = NULL; + reader->free = NULL; + /* Signal the extent of lzop support with the return value here. */ +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) + return (ARCHIVE_OK); +#else + /* Return ARCHIVE_WARN since this always uses an external program. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lzop program for lzop decompression"); + return (ARCHIVE_WARN); +#endif +} + +/* + * Bidder just verifies the header and returns the number of verified bits. + */ +static int +lzop_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *p; + ssize_t avail; + + (void)self; /* UNUSED */ + + p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail); + if (p == NULL || avail == 0) + return (0); + + if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) + return (0); + + return (LZOP_HEADER_MAGIC_LEN * 8); +} + +#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H) +/* + * If we don't have the library on this system, we can't do the + * decompression directly. We can, however, try to run "lzop -d" + * in case that's available. + */ +static int +lzop_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "lzop -d"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_LZOP; + self->name = "lzop"; + return (r); +} +#else +/* + * Initialize the filter object. + */ +static int +lzop_bidder_init(struct archive_read_filter *self) +{ + struct read_lzop *state; + + self->code = ARCHIVE_FILTER_LZOP; + self->name = "lzop"; + + state = (struct read_lzop *)calloc(sizeof(*state), 1); + if (state == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lzop decompression"); + return (ARCHIVE_FATAL); + } + + self->data = state; + self->read = lzop_filter_read; + self->skip = NULL; /* not supported */ + self->close = lzop_filter_close; + + return (ARCHIVE_OK); +} + +static int +consume_header(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const unsigned char *p, *_p; + unsigned checksum, flags, len, method, version; + + /* + * Check LZOP magic code. + */ + p = __archive_read_filter_ahead(self->upstream, + LZOP_HEADER_MAGIC_LEN, NULL); + if (p == NULL) + return (ARCHIVE_EOF); + + if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) + return (ARCHIVE_EOF); + __archive_read_filter_consume(self->upstream, + LZOP_HEADER_MAGIC_LEN); + + p = __archive_read_filter_ahead(self->upstream, 29, NULL); + if (p == NULL) + goto truncated; + _p = p; + version = archive_be16dec(p); + p += 4;/* version(2 bytes) + library version(2 bytes) */ + + if (version >= 0x940) { + unsigned reqversion = archive_be16dec(p); p += 2; + if (reqversion < 0x900) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Invalid required version"); + return (ARCHIVE_FAILED); + } + } + + method = *p++; + if (method < 1 || method > 3) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Unsupported method"); + return (ARCHIVE_FAILED); + } + + if (version >= 0x940) { + unsigned level = *p++; + if (method == 1 && level == 0) level = 3; + if (method == 2 && level == 0) level = 1; + if (method == 3 && level == 0) level = 9; + if (level < 1 && level > 9) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Invalid level"); + return (ARCHIVE_FAILED); + } + } + + flags = archive_be32dec(p); p += 4; + + if (flags & FILTER) + p += 4; /* Skip filter */ + p += 4; /* Skip mode */ + if (version >= 0x940) + p += 8; /* Skip mtime */ + else + p += 4; /* Skip mtime */ + len = *p++; /* Read filename length */ + len += p - _p; + /* Make sure we have all bytes we need to calculate checksum. */ + p = __archive_read_filter_ahead(self->upstream, len + 4, NULL); + if (p == NULL) + goto truncated; + if (flags & CRC32_HEADER) + checksum = crc32(crc32(0, NULL, 0), p, len); + else + checksum = adler32(adler32(0, NULL, 0), p, len); + if (archive_be32dec(p + len) != checksum) + goto corrupted; + __archive_read_filter_consume(self->upstream, len + 4); + if (flags & EXTRA_FIELD) { + /* Skip extra field */ + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + len = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, len + 4 + 4); + } + state->flags = flags; + state->in_stream = 1; + return (ARCHIVE_OK); +truncated: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FAILED); +corrupted: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); + return (ARCHIVE_FAILED); +} + +static int +consume_block_info(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const unsigned char *p; + unsigned flags = state->flags; + + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->uncompressed_size = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + if (state->uncompressed_size == 0) + return (ARCHIVE_EOF); + if (state->uncompressed_size > MAX_BLOCK_SIZE) + goto corrupted; + + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_size = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + if (state->compressed_size > state->uncompressed_size) + goto corrupted; + + if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) { + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_cksum = state->uncompressed_cksum = + archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + } + if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) && + state->compressed_size < state->uncompressed_size) { + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_cksum = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + } + return (ARCHIVE_OK); +truncated: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FAILED); +corrupted: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); + return (ARCHIVE_FAILED); +} + +static ssize_t +lzop_filter_read(struct archive_read_filter *self, const void **p) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const void *b; + lzo_uint out_size; + uint32_t cksum; + int ret, r; + + if (state->unconsumed_bytes) { + __archive_read_filter_consume(self->upstream, + state->unconsumed_bytes); + state->unconsumed_bytes = 0; + } + if (state->eof) + return (0); + + for (;;) { + if (!state->in_stream) { + ret = consume_header(self); + if (ret < ARCHIVE_OK) + return (ret); + if (ret == ARCHIVE_EOF) { + state->eof = 1; + return (0); + } + } + ret = consume_block_info(self); + if (ret < ARCHIVE_OK) + return (ret); + if (ret == ARCHIVE_EOF) + state->in_stream = 0; + else + break; + } + + if (state->out_block == NULL || + state->out_block_size < state->uncompressed_size) { + void *new_block; + + new_block = realloc(state->out_block, state->uncompressed_size); + if (new_block == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lzop decompression"); + return (ARCHIVE_FATAL); + } + state->out_block = new_block; + state->out_block_size = state->uncompressed_size; + } + + b = __archive_read_filter_ahead(self->upstream, + state->compressed_size, NULL); + if (b == NULL) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FATAL); + } + if (state->flags & CRC32_COMPRESSED) + cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size); + else if (state->flags & ADLER32_COMPRESSED) + cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size); + else + cksum = state->compressed_cksum; + if (cksum != state->compressed_cksum) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + } + + /* + * If the both uncompressed size and compressed size are the same, + * we do not decompress this block. + */ + if (state->uncompressed_size == state->compressed_size) { + *p = b; + state->total_out += state->compressed_size; + state->unconsumed_bytes = state->compressed_size; + return ((ssize_t)state->uncompressed_size); + } + + /* + * Drive lzo uncompresison. + */ + out_size = (lzo_uint)state->uncompressed_size; + r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size, + state->out_block, &out_size, NULL); + switch (r) { + case LZO_E_OK: + if (out_size == state->uncompressed_size) + break; + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + case LZO_E_OUT_OF_MEMORY: + archive_set_error(&self->archive->archive, ENOMEM, + "lzop decompression failed: out of memory"); + return (ARCHIVE_FATAL); + default: + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "lzop decompression failed: %d", r); + return (ARCHIVE_FATAL); + } + + if (state->flags & CRC32_UNCOMPRESSED) + cksum = crc32(crc32(0, NULL, 0), state->out_block, + state->uncompressed_size); + else if (state->flags & ADLER32_UNCOMPRESSED) + cksum = adler32(adler32(0, NULL, 0), state->out_block, + state->uncompressed_size); + else + cksum = state->uncompressed_cksum; + if (cksum != state->uncompressed_cksum) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + } + + __archive_read_filter_consume(self->upstream, state->compressed_size); + *p = state->out_block; + state->total_out += out_size; + return ((ssize_t)out_size); +} + +/* + * Clean up the decompressor. + */ +static int +lzop_filter_close(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + + free(state->out_block); + free(state); + return (ARCHIVE_OK); +} + +#endif diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c index b05eb0342..66dc2f424 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2007 Joerg Sonnenberger + * Copyright (c) 2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +54,9 @@ __FBSDID("$FreeBSD$"); #include "archive.h" #include "archive_private.h" +#include "archive_string.h" #include "archive_read_private.h" +#include "filter_fork.h" #if ARCHIVE_VERSION_NUMBER < 4000000 @@ -79,50 +82,13 @@ archive_read_support_filter_program(struct archive *a, const char *cmd) return (archive_read_support_filter_program_signature(a, cmd, NULL, 0)); } - -/* This capability is only available on POSIX systems. */ -#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \ - !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__)) - -/* - * On non-Posix systems, allow the program to build, but choke if - * this function is actually invoked. - */ -int -archive_read_support_filter_program_signature(struct archive *_a, - const char *cmd, const void *signature, size_t signature_len) -{ - (void)_a; /* UNUSED */ - (void)cmd; /* UNUSED */ - (void)signature; /* UNUSED */ - (void)signature_len; /* UNUSED */ - - archive_set_error(_a, -1, - "External compression programs not supported on this platform"); - return (ARCHIVE_FATAL); -} - -int -__archive_read_program(struct archive_read_filter *self, const char *cmd) -{ - (void)self; /* UNUSED */ - (void)cmd; /* UNUSED */ - - archive_set_error(&self->archive->archive, -1, - "External compression programs not supported on this platform"); - return (ARCHIVE_FATAL); -} - -#else - -#include "filter_fork.h" - /* * The bidder object stores the command and the signature to watch for. * The 'inhibit' entry here is used to ensure that unchecked filters never * bid twice in the same pipeline. */ struct program_bidder { + char *description; char *cmd; void *signature; size_t signature_len; @@ -138,8 +104,12 @@ static int program_bidder_free(struct archive_read_filter_bidder *); * The actual filter needs to track input and output data. */ struct program_filter { - char *description; + struct archive_string description; +#if defined(_WIN32) && !defined(__CYGWIN__) + HANDLE child; +#else pid_t child; +#endif int exit_status; int waitpid_return; int child_stdin, child_stdout; @@ -151,6 +121,29 @@ struct program_filter { static ssize_t program_filter_read(struct archive_read_filter *, const void **); static int program_filter_close(struct archive_read_filter *); +static void free_state(struct program_bidder *); + +static int +set_bidder_signature(struct archive_read_filter_bidder *bidder, + struct program_bidder *state, const void *signature, size_t signature_len) +{ + + if (signature != NULL && signature_len > 0) { + state->signature_len = signature_len; + state->signature = malloc(signature_len); + memcpy(state->signature, signature, signature_len); + } + + /* + * Fill in the bidder object. + */ + bidder->data = state; + bidder->bid = program_bidder_bid; + bidder->init = program_bidder_init; + bidder->options = NULL; + bidder->free = program_bidder_free; + return (ARCHIVE_OK); +} int archive_read_support_filter_program_signature(struct archive *_a, @@ -169,37 +162,40 @@ archive_read_support_filter_program_signature(struct archive *_a, /* * Allocate our private state. */ - state = (struct program_bidder *)calloc(sizeof (*state), 1); + state = (struct program_bidder *)calloc(1, sizeof (*state)); if (state == NULL) - return (ARCHIVE_FATAL); + goto memerr; state->cmd = strdup(cmd); - if (signature != NULL && signature_len > 0) { - state->signature_len = signature_len; - state->signature = malloc(signature_len); - memcpy(state->signature, signature, signature_len); - } + if (state->cmd == NULL) + goto memerr; - /* - * Fill in the bidder object. - */ - bidder->data = state; - bidder->bid = program_bidder_bid; - bidder->init = program_bidder_init; - bidder->options = NULL; - bidder->free = program_bidder_free; - return (ARCHIVE_OK); + return set_bidder_signature(bidder, state, signature, signature_len); +memerr: + free_state(state); + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); } static int program_bidder_free(struct archive_read_filter_bidder *self) { struct program_bidder *state = (struct program_bidder *)self->data; - free(state->cmd); - free(state->signature); - free(self->data); + + free_state(state); return (ARCHIVE_OK); } +static void +free_state(struct program_bidder *state) +{ + + if (state) { + free(state->cmd); + free(state->signature); + free(state); + } +} + /* * If we do have a signature, bid only if that matches. * @@ -258,6 +254,9 @@ child_stop(struct archive_read_filter *self, struct program_filter *state) state->waitpid_return = waitpid(state->child, &state->exit_status, 0); } while (state->waitpid_return == -1 && errno == EINTR); +#if defined(_WIN32) && !defined(__CYGWIN__) + CloseHandle(state->child); +#endif state->child = 0; } @@ -310,11 +309,35 @@ child_read(struct archive_read_filter *self, char *buf, size_t buf_len) struct program_filter *state = self->data; ssize_t ret, requested, avail; const char *p; +#if defined(_WIN32) && !defined(__CYGWIN__) + HANDLE handle = (HANDLE)_get_osfhandle(state->child_stdout); +#endif requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len; for (;;) { do { +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Avoid infinity wait. + * Note: If there is no data in the pipe, ReadFile() + * called in read() never returns and so we won't + * write remaining encoded data to the pipe. + * Note: This way may cause performance problem. + * we are looking forward to great code to resolve + * this. */ + DWORD pipe_avail = -1; + int cnt = 2; + + while (PeekNamedPipe(handle, NULL, 0, NULL, + &pipe_avail, NULL) != 0 && pipe_avail == 0 && + cnt--) + Sleep(5); + if (pipe_avail == 0) { + ret = -1; + errno = EAGAIN; + break; + } +#endif ret = read(state->child_stdout, buf, requested); } while (ret == -1 && errno == EINTR); @@ -376,38 +399,57 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd) struct program_filter *state; static const size_t out_buf_len = 65536; char *out_buf; - char *description; const char *prefix = "Program: "; + pid_t child; + size_t l; + l = strlen(prefix) + strlen(cmd) + 1; state = (struct program_filter *)calloc(1, sizeof(*state)); out_buf = (char *)malloc(out_buf_len); - description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1); - if (state == NULL || out_buf == NULL || description == NULL) { + if (state == NULL || out_buf == NULL || + archive_string_ensure(&state->description, l) == NULL) { archive_set_error(&self->archive->archive, ENOMEM, "Can't allocate input data"); - free(state); + if (state != NULL) { + archive_string_free(&state->description); + free(state); + } free(out_buf); - free(description); return (ARCHIVE_FATAL); } + archive_strcpy(&state->description, prefix); + archive_strcat(&state->description, cmd); - self->code = ARCHIVE_COMPRESSION_PROGRAM; - state->description = description; - strcpy(state->description, prefix); - strcat(state->description, cmd); - self->name = state->description; + self->code = ARCHIVE_FILTER_PROGRAM; + self->name = state->description.s; state->out_buf = out_buf; state->out_buf_len = out_buf_len; - if ((state->child = __archive_create_child(cmd, - &state->child_stdin, &state->child_stdout)) == -1) { + child = __archive_create_child(cmd, &state->child_stdin, + &state->child_stdout); + if (child == -1) { + free(state->out_buf); + free(state); + archive_set_error(&self->archive->archive, EINVAL, + "Can't initialize filter; unable to run program \"%s\"", + cmd); + return (ARCHIVE_FATAL); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + state->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child); + if (state->child == NULL) { + child_stop(self, state); free(state->out_buf); free(state); archive_set_error(&self->archive->archive, EINVAL, - "Can't initialize filter; unable to run program \"%s\"", cmd); + "Can't initialize filter; unable to run program \"%s\"", + cmd); return (ARCHIVE_FATAL); } +#else + state->child = child; +#endif self->data = state; self->read = program_filter_read; @@ -467,10 +509,8 @@ program_filter_close(struct archive_read_filter *self) /* Release our private data. */ free(state->out_buf); - free(state->description); + archive_string_free(&state->description); free(state); return (e); } - -#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */ diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_rpm.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_rpm.c index 7dbfc0ebc..e7e58e51f 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_rpm.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_rpm.c @@ -85,6 +85,7 @@ archive_read_support_filter_rpm(struct archive *_a) return (ARCHIVE_FATAL); bidder->data = NULL; + bidder->name = "rpm"; bidder->bid = rpm_bidder_bid; bidder->init = rpm_bidder_init; bidder->options = NULL; @@ -137,7 +138,7 @@ rpm_bidder_init(struct archive_read_filter *self) { struct rpm *rpm; - self->code = ARCHIVE_COMPRESSION_RPM; + self->code = ARCHIVE_FILTER_RPM; self->name = "rpm"; self->read = rpm_filter_read; self->skip = NULL; /* not supported */ @@ -188,7 +189,7 @@ rpm_filter_read(struct archive_read_filter *self, const void **buff) if (rpm->total_in + avail_in < RPM_LEAD_SIZE) used += avail_in; else { - n = RPM_LEAD_SIZE - rpm->total_in; + n = (size_t)(RPM_LEAD_SIZE - rpm->total_in); used += n; b += n; rpm->state = ST_HEADER; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c index a75ef7560..471771b6f 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c @@ -56,6 +56,7 @@ struct uudecode { #define ST_READ_UU 1 #define ST_UUEND 2 #define ST_READ_BASE64 3 +#define ST_IGNORE 4 }; static int uudecode_bidder_bid(struct archive_read_filter_bidder *, @@ -88,6 +89,7 @@ archive_read_support_filter_uu(struct archive *_a) return (ARCHIVE_FATAL); bidder->data = NULL; + bidder->name = "uu"; bidder->bid = uudecode_bidder_bid; bidder->init = uudecode_bidder_init; bidder->options = NULL; @@ -377,7 +379,7 @@ uudecode_bidder_init(struct archive_read_filter *self) void *out_buff; void *in_buff; - self->code = ARCHIVE_COMPRESSION_UU; + self->code = ARCHIVE_FILTER_UU; self->name = "uu"; self->read = uudecode_filter_read; self->skip = NULL; /* not supported */ @@ -470,6 +472,10 @@ read_more: total = 0; out = uudecode->out_buff; ravail = avail_in; + if (uudecode->state == ST_IGNORE) { + used = avail_in; + goto finish; + } if (uudecode->in_cnt) { /* * If there is remaining data which is saved by @@ -485,12 +491,18 @@ read_more: uudecode->in_cnt = 0; } for (;used < avail_in; d += llen, used += llen) { - int l, body; + int64_t l, body; b = d; len = get_line(b, avail_in - used, &nl); if (len < 0) { /* Non-ascii character is found. */ + if (uudecode->state == ST_FIND_HEAD && + (uudecode->total > 0 || total > 0)) { + uudecode->state = ST_IGNORE; + used = avail_in; + goto finish; + } archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Insufficient compressed data"); @@ -507,7 +519,7 @@ read_more: return (ARCHIVE_FATAL); if (uudecode->in_buff != b) memmove(uudecode->in_buff, b, len); - uudecode->in_cnt = len; + uudecode->in_cnt = (int)len; if (total == 0) { /* Do not return 0; it means end-of-file. * We should try to read bytes more. */ @@ -545,7 +557,7 @@ read_more: break; case ST_READ_UU: if (total + len * 2 > OUT_BUFF_SIZE) - break; + goto finish; body = len - nl; if (!uuchar[*b] || body <= 0) { archive_set_error(&self->archive->archive, @@ -611,7 +623,7 @@ read_more: break; case ST_READ_BASE64: if (total + len * 2 > OUT_BUFF_SIZE) - break; + goto finish; l = len - nl; if (l >= 3 && b[0] == '=' && b[1] == '=' && b[2] == '=') { @@ -657,8 +669,10 @@ read_more: break; } } - - __archive_read_filter_consume(self->upstream, ravail); +finish: + if (ravail < avail_in) + used -= avail_in - ravail; + __archive_read_filter_consume(self->upstream, used); *buff = uudecode->out_buff; uudecode->total += total; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c index cf762a46d..15824b1d0 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c @@ -136,6 +136,7 @@ archive_read_support_filter_xz(struct archive *_a) return (ARCHIVE_FATAL); bidder->data = NULL; + bidder->name = "xz"; bidder->bid = xz_bidder_bid; bidder->init = xz_bidder_init; bidder->options = NULL; @@ -144,7 +145,7 @@ archive_read_support_filter_xz(struct archive *_a) return (ARCHIVE_OK); #else archive_set_error(_a, ARCHIVE_ERRNO_MISC, - "Using external unxz program for xz decompression"); + "Using external xz program for xz decompression"); return (ARCHIVE_WARN); #endif } @@ -170,6 +171,7 @@ archive_read_support_filter_lzma(struct archive *_a) return (ARCHIVE_FATAL); bidder->data = NULL; + bidder->name = "lzma"; bidder->bid = lzma_bidder_bid; bidder->init = lzma_bidder_init; bidder->options = NULL; @@ -180,7 +182,7 @@ archive_read_support_filter_lzma(struct archive *_a) return (ARCHIVE_OK); #else archive_set_error(_a, ARCHIVE_ERRNO_MISC, - "Using external unlzma program for lzma decompression"); + "Using external lzma program for lzma decompression"); return (ARCHIVE_WARN); #endif } @@ -207,6 +209,7 @@ archive_read_support_filter_lzip(struct archive *_a) return (ARCHIVE_FATAL); bidder->data = NULL; + bidder->name = "lzip"; bidder->bid = lzip_bidder_bid; bidder->init = lzip_bidder_init; bidder->options = NULL; @@ -415,7 +418,7 @@ lzip_bidder_bid(struct archive_read_filter_bidder *self, static int xz_bidder_init(struct archive_read_filter *self) { - self->code = ARCHIVE_COMPRESSION_XZ; + self->code = ARCHIVE_FILTER_XZ; self->name = "xz"; return (xz_lzma_bidder_init(self)); } @@ -423,7 +426,7 @@ xz_bidder_init(struct archive_read_filter *self) static int lzma_bidder_init(struct archive_read_filter *self) { - self->code = ARCHIVE_COMPRESSION_LZMA; + self->code = ARCHIVE_FILTER_LZMA; self->name = "lzma"; return (xz_lzma_bidder_init(self)); } @@ -431,7 +434,7 @@ lzma_bidder_init(struct archive_read_filter *self) static int lzip_bidder_init(struct archive_read_filter *self) { - self->code = ARCHIVE_COMPRESSION_LZIP; + self->code = ARCHIVE_FILTER_LZIP; self->name = "lzip"; return (xz_lzma_bidder_init(self)); } @@ -518,7 +521,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self) state->stream.avail_out = state->out_block_size; state->crc32 = 0; - if (self->code == ARCHIVE_COMPRESSION_LZIP) { + if (self->code == ARCHIVE_FILTER_LZIP) { /* * We have to read a lzip header and use it to initialize * compression library, thus we cannot initialize the @@ -530,7 +533,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self) state->in_stream = 1; /* Initialize compression library. */ - if (self->code == ARCHIVE_COMPRESSION_XZ) + if (self->code == ARCHIVE_FILTER_XZ) ret = lzma_stream_decoder(&(state->stream), LZMA_MEMLIMIT,/* memlimit */ LZMA_CONCATENATED); @@ -730,7 +733,7 @@ xz_filter_read(struct archive_read_filter *self, const void **p) *p = NULL; else { *p = state->out_block; - if (self->code == ARCHIVE_COMPRESSION_LZIP) { + if (self->code == ARCHIVE_FILTER_LZIP) { state->crc32 = lzma_crc32(state->out_block, decompressed, state->crc32); if (state->eof) { @@ -778,7 +781,7 @@ lzma_bidder_init(struct archive_read_filter *self) struct private_data *state; ssize_t ret, avail_in; - self->code = ARCHIVE_COMPRESSION_LZMA; + self->code = ARCHIVE_FILTER_LZMA; self->name = "lzma"; state = (struct private_data *)calloc(sizeof(*state), 1); @@ -941,11 +944,11 @@ lzma_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_program(self, "unlzma"); + r = __archive_read_program(self, "lzma -d -qq"); /* Note: We set the format here even if __archive_read_program() * above fails. We do, after all, know what the format is * even if we weren't able to read it. */ - self->code = ARCHIVE_COMPRESSION_LZMA; + self->code = ARCHIVE_FILTER_LZMA; self->name = "lzma"; return (r); } @@ -958,11 +961,11 @@ xz_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_program(self, "unxz"); + r = __archive_read_program(self, "xz -d -qq"); /* Note: We set the format here even if __archive_read_program() * above fails. We do, after all, know what the format is * even if we weren't able to read it. */ - self->code = ARCHIVE_COMPRESSION_XZ; + self->code = ARCHIVE_FILTER_XZ; self->name = "xz"; return (r); } @@ -972,11 +975,11 @@ lzip_bidder_init(struct archive_read_filter *self) { int r; - r = __archive_read_program(self, "unlzip"); + r = __archive_read_program(self, "lzip -d -q"); /* Note: We set the format here even if __archive_read_program() * above fails. We do, after all, know what the format is * even if we weren't able to read it. */ - self->code = ARCHIVE_COMPRESSION_LZIP; + self->code = ARCHIVE_FILTER_LZIP; self->name = "lzip"; return (r); } diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c index 2be226726..54ea24590 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c @@ -318,7 +318,7 @@ struct _7zip { uint32_t bcj2_code; uint64_t bcj2_outPos; - /* Filename character-set convertion data. */ + /* Filename character-set conversion data. */ struct archive_string_conv *sconv; char format_name[64]; @@ -409,6 +409,7 @@ archive_read_support_format_7zip(struct archive *_a) archive_read_format_7zip_read_header, archive_read_format_7zip_read_data, archive_read_format_7zip_read_data_skip, + NULL, archive_read_format_7zip_cleanup); if (r != ARCHIVE_OK) @@ -481,7 +482,7 @@ check_7zip_header_in_sfx(const char *p) * Magic Code, so we should do this in order not to * make a mis-detection. */ - if (crc32(0, (unsigned char *)p + 12, 20) + if (crc32(0, (const unsigned char *)p + 12, 20) != archive_le32dec(p + 8)) return (6); /* Hit the header! */ @@ -580,7 +581,7 @@ archive_read_format_7zip_read_header(struct archive_read *a, free_Header(&header); if (r != ARCHIVE_OK) return (r); - zip->entries_remaining = zip->numFiles; + zip->entries_remaining = (size_t)zip->numFiles; zip->entry = zip->entries; } else { ++zip->entry; @@ -630,7 +631,7 @@ archive_read_format_7zip_read_header(struct archive_read *a, if (zip_entry->flg & ATIME_IS_SET) archive_entry_set_atime(entry, zip_entry->atime, zip_entry->atime_ns); - if (zip_entry->ssIndex != -1) { + if (zip_entry->ssIndex != (uint32_t)-1) { zip->entry_bytes_remaining = zip->si.ss.unpackSizes[zip_entry->ssIndex]; archive_entry_set_size(entry, zip->entry_bytes_remaining); @@ -646,7 +647,6 @@ archive_read_format_7zip_read_header(struct archive_read *a, if ((zip_entry->mode & AE_IFMT) == AE_IFLNK) { unsigned char *symname = NULL; size_t symsize = 0; - int r; /* * Symbolic-name is recorded as its contents. We have to @@ -654,19 +654,24 @@ archive_read_format_7zip_read_header(struct archive_read *a, */ while (zip->entry_bytes_remaining > 0) { const void *buff; + unsigned char *mem; size_t size; int64_t offset; r = archive_read_format_7zip_read_data(a, &buff, &size, &offset); - if (r < ARCHIVE_WARN) + if (r < ARCHIVE_WARN) { + free(symname); return (r); - symname = realloc(symname, symsize + size + 1); - if (symname == NULL) { + } + mem = realloc(symname, symsize + size + 1); + if (mem == NULL) { + free(symname); archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Symname"); return (ARCHIVE_FATAL); } + symname = mem; memcpy(symname+symsize, buff, size); symsize += size; } @@ -680,8 +685,8 @@ archive_read_format_7zip_read_header(struct archive_read *a, symname[symsize] = '\0'; archive_entry_copy_symlink(entry, (const char *)symname); - free(symname); } + free(symname); archive_entry_set_size(entry, 0); } @@ -705,18 +710,18 @@ archive_read_format_7zip_read_data(struct archive_read *a, if (zip->pack_stream_bytes_unconsumed) read_consume(a); + *offset = zip->entry_offset; + *size = 0; + *buff = NULL; /* * If we hit end-of-entry last time, clean up and return * ARCHIVE_EOF this time. */ - if (zip->end_of_entry) { - *offset = zip->entry_offset; - *size = 0; - *buff = NULL; + if (zip->end_of_entry) return (ARCHIVE_EOF); - } - bytes = read_stream(a, buff, zip->entry_bytes_remaining, 0); + bytes = read_stream(a, buff, + (size_t)zip->entry_bytes_remaining, 0); if (bytes < 0) return ((int)bytes); if (bytes == 0) { @@ -731,7 +736,8 @@ archive_read_format_7zip_read_data(struct archive_read *a, /* Update checksum */ if ((zip->entry->flg & CRC32_IS_SET) && bytes) - zip->entry_crc32 = crc32(zip->entry_crc32, *buff, bytes); + zip->entry_crc32 = crc32(zip->entry_crc32, *buff, + (unsigned)bytes); /* If we hit the end, swallow any end-of-data marker. */ if (zip->end_of_entry) { @@ -774,7 +780,7 @@ archive_read_format_7zip_read_data_skip(struct archive_read *a) * If the length is at the beginning, we can skip the * compressed data much more quickly. */ - bytes_skipped = skip_stream(a, zip->entry_bytes_remaining); + bytes_skipped = skip_stream(a, (size_t)zip->entry_bytes_remaining); if (bytes_skipped < 0) return (ARCHIVE_FATAL); zip->entry_bytes_remaining = 0; @@ -1054,7 +1060,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, ff = &filters[fi]; #endif r = lzma_properties_decode(&filters[fi], NULL, - coder1->properties, coder1->propertiesSize); + coder1->properties, (size_t)coder1->propertiesSize); if (r != LZMA_OK) { set_error(a, r); return (ARCHIVE_FAILED); @@ -1358,9 +1364,9 @@ decompress(struct archive_read *a, struct _7zip *zip, #ifdef HAVE_ZLIB_H case _7Z_DEFLATE: zip->stream.next_in = (Bytef *)(uintptr_t)t_next_in; - zip->stream.avail_in = t_avail_in; + zip->stream.avail_in = (uInt)t_avail_in; zip->stream.next_out = t_next_out; - zip->stream.avail_out = t_avail_out; + zip->stream.avail_out = (uInt)t_avail_out; r = inflate(&(zip->stream), 0); switch (r) { case Z_STREAM_END: /* Found end of stream. */ @@ -1382,7 +1388,7 @@ decompress(struct archive_read *a, struct _7zip *zip, uint64_t flush_bytes; if (!zip->ppmd7_valid || zip->ppmd7_stat < 0 || - t_avail_in < 0 || t_avail_out <= 0) { + t_avail_out <= 0) { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, "Decompression internal error"); @@ -1442,8 +1448,8 @@ decompress(struct archive_read *a, struct _7zip *zip, } while (zip->ppstream.avail_out && (zip->ppstream.avail_in || flush_bytes)); - t_avail_in = zip->ppstream.avail_in; - t_avail_out = zip->ppstream.avail_out; + t_avail_in = (size_t)zip->ppstream.avail_in; + t_avail_out = (size_t)zip->ppstream.avail_out; break; } default: @@ -1506,6 +1512,10 @@ free_decompression(struct archive_read *a, struct _7zip *zip) { int r = ARCHIVE_OK; +#if !defined(HAVE_ZLIB_H) &&\ + !(defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)) + (void)a;/* UNUSED */ +#endif #ifdef HAVE_LZMA_H if (zip->lzstream_valid) lzma_end(&(zip->lzstream)); @@ -1598,9 +1608,10 @@ read_Digests(struct archive_read *a, struct _7z_digests *d, size_t num) const unsigned char *p; unsigned i; + if (num == 0) + return (-1); memset(d, 0, sizeof(*d)); - d->defineds = malloc(num); if (d->defineds == NULL) return (-1); @@ -1672,8 +1683,8 @@ read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi) return (0); if (*p != kSize) return (-1); - pi->sizes = calloc(pi->numPackStreams, sizeof(uint64_t)); - pi->positions = calloc(pi->numPackStreams, sizeof(uint64_t)); + pi->sizes = calloc((size_t)pi->numPackStreams, sizeof(uint64_t)); + pi->positions = calloc((size_t)pi->numPackStreams, sizeof(uint64_t)); if (pi->sizes == NULL || pi->positions == NULL) return (-1); @@ -1690,9 +1701,9 @@ read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi) if (*p == kEnd) { /* PackStreamDigests[num] are not present. */ pi->digest.defineds = - calloc(pi->numPackStreams, sizeof(*pi->digest.defineds)); + calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.defineds)); pi->digest.digests = - calloc(pi->numPackStreams, sizeof(*pi->digest.digests)); + calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.digests)); if (pi->digest.defineds == NULL || pi->digest.digests == NULL) return (-1); return (0); @@ -1701,7 +1712,7 @@ read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi) if (*p != kSize) return (-1); - if (read_Digests(a, &(pi->digest), pi->numPackStreams) < 0) + if (read_Digests(a, &(pi->digest), (size_t)pi->numPackStreams) < 0) return (-1); /* @@ -1750,7 +1761,7 @@ read_Folder(struct archive_read *a, struct _7z_folder *f) /* Too many coders. */ return (-1); - f->coders = calloc(f->numCoders, sizeof(*f->coders)); + f->coders = calloc((size_t)f->numCoders, sizeof(*f->coders)); if (f->coders == NULL) return (-1); for (i = 0; i< f->numCoders; i++) { @@ -1802,14 +1813,14 @@ read_Folder(struct archive_read *a, struct _7z_folder *f) a, &(f->coders[i].propertiesSize)) < 0) return (-1); if ((p = header_bytes( - a, f->coders[i].propertiesSize)) == NULL) + a, (size_t)f->coders[i].propertiesSize)) == NULL) return (-1); f->coders[i].properties = - malloc(f->coders[i].propertiesSize); + malloc((size_t)f->coders[i].propertiesSize); if (f->coders[i].properties == NULL) return (-1); memcpy(f->coders[i].properties, p, - f->coders[i].propertiesSize); + (size_t)f->coders[i].propertiesSize); } numInStreamsTotal += f->coders[i].numInStreams; @@ -1823,9 +1834,13 @@ read_Folder(struct archive_read *a, struct _7z_folder *f) f->numBindPairs = numOutStreamsTotal - 1; if (zip->header_bytes_remaining < f->numBindPairs) return (-1); - f->bindPairs = calloc(f->numBindPairs, sizeof(*f->bindPairs)); - if (f->bindPairs == NULL) - return (-1); + if (f->numBindPairs > 0) { + f->bindPairs = + calloc((size_t)f->numBindPairs, sizeof(*f->bindPairs)); + if (f->bindPairs == NULL) + return (-1); + } else + f->bindPairs = NULL; for (i = 0; i < f->numBindPairs; i++) { if (parse_7zip_uint64(a, &(f->bindPairs[i].inIndex)) < 0) return (-1); @@ -1839,7 +1854,7 @@ read_Folder(struct archive_read *a, struct _7z_folder *f) f->numPackedStreams = numInStreamsTotal - f->numBindPairs; f->packedStreams = - calloc(f->numPackedStreams, sizeof(*f->packedStreams)); + calloc((size_t)f->numPackedStreams, sizeof(*f->packedStreams)); if (f->packedStreams == NULL) return (-1); if (f->numPackedStreams == 1) { @@ -1911,7 +1926,8 @@ read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci) goto failed; switch (*p) { case 0: - ci->folders = calloc(ci->numFolders, sizeof(*ci->folders)); + ci->folders = + calloc((size_t)ci->numFolders, sizeof(*ci->folders)); if (ci->folders == NULL) return (-1); for (i = 0; i < ci->numFolders; i++) { @@ -1937,7 +1953,7 @@ read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci) unsigned j; folder->unPackSize = - calloc(folder->numOutStreams, sizeof(*folder->unPackSize)); + calloc((size_t)folder->numOutStreams, sizeof(*folder->unPackSize)); if (folder->unPackSize == NULL) goto failed; for (j = 0; j < folder->numOutStreams; j++) { @@ -1955,7 +1971,7 @@ read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci) return (0); if (*p != kCRC) goto failed; - if (read_Digests(a, &digest, ci->numFolders) < 0) + if (read_Digests(a, &digest, (size_t)ci->numFolders) < 0) goto failed; for (i = 0; i < ci->numFolders; i++) { ci->folders[i].digest_defined = digest.defineds[i]; @@ -1979,13 +1995,13 @@ failed: static uint64_t folder_uncompressed_size(struct _7z_folder *f) { - int n = f->numOutStreams; - unsigned pairs = f->numBindPairs; + int n = (int)f->numOutStreams; + unsigned pairs = (unsigned)f->numBindPairs; while (--n >= 0) { unsigned i; for (i = 0; i < pairs; i++) { - if (f->bindPairs[i].outIndex == n) + if (f->bindPairs[i].outIndex == (uint64_t)n) break; } if (i >= pairs) @@ -2029,7 +2045,7 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, return (-1); if (1000000 < f[i].numUnpackStreams) return (-1); - unpack_streams += f[i].numUnpackStreams; + unpack_streams += (size_t)f[i].numUnpackStreams; } if ((p = header_bytes(a, 1)) == NULL) return (-1); @@ -2083,7 +2099,7 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, numDigests = 0; for (i = 0; i < numFolders; i++) { if (f[i].numUnpackStreams != 1 || !f[i].digest_defined) - numDigests += f[i].numUnpackStreams; + numDigests += (uint32_t)f[i].numUnpackStreams; } if (type == kCRC) { @@ -2181,7 +2197,7 @@ read_StreamsInfo(struct archive_read *a, struct _7z_stream_info *si) f = si->ci.folders; for (i = 0; i < si->ci.numFolders; i++) { f[i].packIndex = packIndex; - packIndex += f[i].numPackedStreams; + packIndex += (uint32_t)f[i].numPackedStreams; if (packIndex > si->pi.numPackStreams) return (-1); } @@ -2191,7 +2207,7 @@ read_StreamsInfo(struct archive_read *a, struct _7z_stream_info *si) if (*p == kSubStreamsInfo) { if (read_SubStreamsInfo(a, &(si->ss), - si->ci.folders, si->ci.numFolders) < 0) + si->ci.folders, (size_t)si->ci.numFolders) < 0) return (-1); if ((p = header_bytes(a, 1)) == NULL) return (-1); @@ -2279,7 +2295,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if (1000000 < zip->numFiles) return (-1); - zip->entries = calloc(zip->numFiles, sizeof(*zip->entries)); + zip->entries = calloc((size_t)zip->numFiles, sizeof(*zip->entries)); if (zip->entries == NULL) return (-1); entries = zip->entries; @@ -2304,12 +2320,12 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, switch (type) { case kEmptyStream: - h->emptyStreamBools = calloc(zip->numFiles, + h->emptyStreamBools = calloc((size_t)zip->numFiles, sizeof(*h->emptyStreamBools)); if (h->emptyStreamBools == NULL) return (-1); if (read_Bools( - a, h->emptyStreamBools, zip->numFiles) < 0) + a, h->emptyStreamBools, (size_t)zip->numFiles) < 0) return (-1); empty_streams = 0; for (i = 0; i < zip->numFiles; i++) { @@ -2318,6 +2334,12 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, } break; case kEmptyFile: + if (empty_streams <= 0) { + /* Unexcepted sequence. Skip this. */ + if (header_bytes(a, ll) == NULL) + return (-1); + break; + } h->emptyFileBools = calloc(empty_streams, sizeof(*h->emptyFileBools)); if (h->emptyFileBools == NULL) @@ -2326,6 +2348,12 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, return (-1); break; case kAnti: + if (empty_streams <= 0) { + /* Unexcepted sequence. Skip this. */ + if (header_bytes(a, ll) == NULL) + return (-1); + break; + } h->antiBools = calloc(empty_streams, sizeof(*h->antiBools)); if (h->antiBools == NULL) @@ -2404,15 +2432,15 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if ((p = header_bytes(a, 2)) == NULL) return (-1); allAreDefined = *p; - h->attrBools = calloc(zip->numFiles, + h->attrBools = calloc((size_t)zip->numFiles, sizeof(*h->attrBools)); if (h->attrBools == NULL) return (-1); if (allAreDefined) - memset(h->attrBools, 1, zip->numFiles); + memset(h->attrBools, 1, (size_t)zip->numFiles); else { if (read_Bools(a, h->attrBools, - zip->numFiles) < 0) + (size_t)zip->numFiles) < 0) return (-1); } for (i = 0; i < zip->numFiles; i++) { @@ -2446,7 +2474,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if ((size_t)sindex >= si->ss.unpack_streams) return (-1); if (entries[i].mode == 0) - entries[i].mode = AE_IFREG | 0777; + entries[i].mode = AE_IFREG | 0666; if (si->ss.digestsDefined[sindex]) entries[i].flg |= CRC32_IS_SET; entries[i].ssIndex = sindex; @@ -2466,7 +2494,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if (dir) entries[i].mode = AE_IFDIR | 0777; else - entries[i].mode = AE_IFREG | 0777; + entries[i].mode = AE_IFREG | 0666; } else if (dir && (entries[i].mode & AE_IFMT) != AE_IFDIR) { entries[i].mode &= ~AE_IFMT; @@ -2517,17 +2545,17 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) static void -fileTimeToUtc(uint64_t fileTime, time_t *time, long *ns) +fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns) { if (fileTime >= EPOC_TIME) { fileTime -= EPOC_TIME; /* milli seconds base */ - *time = (time_t)(fileTime / 10000000); + *timep = (time_t)(fileTime / 10000000); /* nano seconds base */ *ns = (long)(fileTime % 10000000) * 100; } else { - *time = 0; + *timep = 0; *ns = 0; } } @@ -2542,7 +2570,7 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type) int allAreDefined; unsigned i; - timeBools = calloc(zip->numFiles, sizeof(*timeBools)); + timeBools = calloc((size_t)zip->numFiles, sizeof(*timeBools)); if (timeBools == NULL) return (-1); @@ -2551,9 +2579,9 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type) goto failed; allAreDefined = *p; if (allAreDefined) - memset(timeBools, 1, zip->numFiles); + memset(timeBools, 1, (size_t)zip->numFiles); else { - if (read_Bools(a, timeBools, zip->numFiles) < 0) + if (read_Bools(a, timeBools, (size_t)zip->numFiles) < 0) goto failed; } @@ -2564,7 +2592,7 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type) if (parse_7zip_uint64(a, &(h->dataIndex)) < 0) goto failed; if (1000000 < h->dataIndex) - return (-1); + goto failed; } for (i = 0; i < zip->numFiles; i++) { @@ -2661,7 +2689,7 @@ header_bytes(struct archive_read *a, size_t rbytes) } /* Update checksum */ - zip->header_crc32 = crc32(zip->header_crc32, p, rbytes); + zip->header_crc32 = crc32(zip->header_crc32, p, (unsigned)rbytes); return (p); } @@ -2695,7 +2723,8 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, } /* CRC check. */ - if (crc32(0, (unsigned char *)p + 12, 20) != archive_le32dec(p + 8)) { + if (crc32(0, (const unsigned char *)p + 12, 20) + != archive_le32dec(p + 8)) { archive_set_error(&a->archive, -1, "Header CRC error"); return (ARCHIVE_FATAL); } @@ -2714,7 +2743,7 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, } __archive_read_consume(a, 32); if (next_header_offset != 0) { - if (bytes_avail >= next_header_offset) + if (bytes_avail >= (ssize_t)next_header_offset) __archive_read_consume(a, next_header_offset); else if (__archive_read_seek(a, next_header_offset + zip->seek_base, SEEK_SET) < 0) @@ -2827,7 +2856,7 @@ get_uncompressed_data(struct archive_read *a, const void **buff, size_t size, struct _7zip *zip = (struct _7zip *)a->format->data; ssize_t bytes_avail; - if (zip->codec == _7Z_COPY && zip->codec2 == -1) { + if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) { /* Copy mode. */ /* @@ -2886,7 +2915,7 @@ extract_pack_stream(struct archive_read *a, size_t minimum) ssize_t bytes_avail; int r; - if (zip->codec == _7Z_COPY && zip->codec2 == -1) { + if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) { if (minimum == 0) minimum = 1; if (__archive_read_ahead(a, minimum, &bytes_avail) == NULL @@ -2896,11 +2925,11 @@ extract_pack_stream(struct archive_read *a, size_t minimum) "Truncated 7-Zip file body"); return (ARCHIVE_FATAL); } - if (bytes_avail > zip->pack_stream_inbytes_remaining) - bytes_avail = zip->pack_stream_inbytes_remaining; + if (bytes_avail > (ssize_t)zip->pack_stream_inbytes_remaining) + bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining; zip->pack_stream_inbytes_remaining -= bytes_avail; - if (bytes_avail > zip->folder_outbytes_remaining) - bytes_avail = zip->folder_outbytes_remaining; + if (bytes_avail > (ssize_t)zip->folder_outbytes_remaining) + bytes_avail = (ssize_t)zip->folder_outbytes_remaining; zip->folder_outbytes_remaining -= bytes_avail; zip->uncompressed_buffer_bytes_remaining = bytes_avail; return (ARCHIVE_OK); @@ -2939,16 +2968,19 @@ extract_pack_stream(struct archive_read *a, size_t minimum) * Expand the uncompressed buffer up to * the minimum size. */ - zip->uncompressed_buffer_size = minimum + 1023; - zip->uncompressed_buffer_size &= ~0x3ff; - zip->uncompressed_buffer = - realloc(zip->uncompressed_buffer, - zip->uncompressed_buffer_size); - if (zip->uncompressed_buffer == NULL) { + void *p; + size_t new_size; + + new_size = minimum + 1023; + new_size &= ~0x3ff; + p = realloc(zip->uncompressed_buffer, new_size); + if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "No memory for 7-Zip decompression"); return (ARCHIVE_FATAL); } + zip->uncompressed_buffer = (unsigned char *)p; + zip->uncompressed_buffer_size = new_size; } /* * Move unconsumed bytes to the head. @@ -2965,7 +2997,7 @@ extract_pack_stream(struct archive_read *a, size_t minimum) size_t bytes_in, bytes_out; const void *buff_in; unsigned char *buff_out; - int eof; + int end_of_data; /* * Note: '1' here is a performance optimization. @@ -2987,23 +3019,23 @@ extract_pack_stream(struct archive_read *a, size_t minimum) - zip->uncompressed_buffer_bytes_remaining; bytes_in = bytes_avail; if (bytes_in > zip->pack_stream_inbytes_remaining) - bytes_in = zip->pack_stream_inbytes_remaining; + bytes_in = (size_t)zip->pack_stream_inbytes_remaining; /* Drive decompression. */ r = decompress(a, zip, buff_out, &bytes_out, buff_in, &bytes_in); switch (r) { case ARCHIVE_OK: - eof = 0; + end_of_data = 0; break; case ARCHIVE_EOF: - eof = 1; + end_of_data = 1; break; default: return (ARCHIVE_FATAL); } zip->pack_stream_inbytes_remaining -= bytes_in; if (bytes_out > zip->folder_outbytes_remaining) - bytes_out = zip->folder_outbytes_remaining; + bytes_out = (size_t)zip->folder_outbytes_remaining; zip->folder_outbytes_remaining -= bytes_out; zip->uncompressed_buffer_bytes_remaining += bytes_out; zip->pack_stream_bytes_unconsumed = bytes_in; @@ -3021,7 +3053,7 @@ extract_pack_stream(struct archive_read *a, size_t minimum) if (zip->pack_stream_inbytes_remaining == 0 && zip->folder_outbytes_remaining == 0) break; - if (eof || (bytes_in == 0 && bytes_out == 0)) { + if (end_of_data || (bytes_in == 0 && bytes_out == 0)) { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive"); return (ARCHIVE_FATAL); @@ -3041,7 +3073,7 @@ static int seek_pack(struct archive_read *a) { struct _7zip *zip = (struct _7zip *)a->format->data; - uint64_t pack_offset; + int64_t pack_offset; if (zip->pack_stream_remaining <= 0) { archive_set_error(&(a->archive), @@ -3068,7 +3100,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size, { struct _7zip *zip = (struct _7zip *)a->format->data; uint64_t skip_bytes = 0; - int r; + ssize_t r; if (zip->uncompressed_buffer_bytes_remaining == 0) { if (zip->pack_stream_inbytes_remaining > 0) { @@ -3160,7 +3192,8 @@ read_stream(struct archive_read *a, const void **buff, size_t size, return (ARCHIVE_FATAL); } } - skipped = get_uncompressed_data(a, buff, skip_bytes, 0); + skipped = get_uncompressed_data( + a, buff, (size_t)skip_bytes, 0); if (skipped < 0) return (skipped); skip_bytes -= skipped; @@ -3292,13 +3325,13 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, } coder2 = &(fc[3]); zip->main_stream_bytes_remaining = - folder->unPackSize[2]; + (size_t)folder->unPackSize[2]; } else if (coder2 != NULL && coder2->codec == _7Z_X86_BCJ2 && zip->pack_stream_remaining == 4 && folder->numInStreams == 5 && folder->numOutStreams == 2) { /* Source type 0 made by 7z */ zip->main_stream_bytes_remaining = - folder->unPackSize[0]; + (size_t)folder->unPackSize[0]; } else { /* We got an unexpected form. */ archive_set_error(&(a->archive), @@ -3311,30 +3344,35 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, if ((r = seek_pack(a)) < 0) return (r); zip->pack_stream_bytes_unconsumed = - zip->pack_stream_inbytes_remaining; + (size_t)zip->pack_stream_inbytes_remaining; read_consume(a); /* Read following three sub streams. */ for (i = 0; i < 3; i++) { const struct _7z_coder *coder = scoder[i]; - if ((r = seek_pack(a)) < 0) + if ((r = seek_pack(a)) < 0) { + free(b[0]); free(b[1]); free(b[2]); return (r); + } - if (sunpack[i] == -1) + if (sunpack[i] == (uint64_t)-1) zip->folder_outbytes_remaining = zip->pack_stream_inbytes_remaining; else zip->folder_outbytes_remaining = sunpack[i]; r = init_decompression(a, zip, coder, NULL); - if (r != ARCHIVE_OK) + if (r != ARCHIVE_OK) { + free(b[0]); free(b[1]); free(b[2]); return (ARCHIVE_FATAL); + } /* Allocate memory for the decorded data of a sub * stream. */ - b[i] = malloc(zip->folder_outbytes_remaining); + b[i] = malloc((size_t)zip->folder_outbytes_remaining); if (b[i] == NULL) { + free(b[0]); free(b[1]); free(b[2]); archive_set_error(&a->archive, ENOMEM, "No memory for 7-Zip decompression"); return (ARCHIVE_FATAL); @@ -3342,14 +3380,18 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, /* Extract a sub stream. */ while (zip->pack_stream_inbytes_remaining > 0) { - r = extract_pack_stream(a, 0); - if (r < 0) + r = (int)extract_pack_stream(a, 0); + if (r < 0) { + free(b[0]); free(b[1]); free(b[2]); return (r); + } bytes = get_uncompressed_data(a, &buff, zip->uncompressed_buffer_bytes_remaining, 0); - if (bytes < 0) + if (bytes < 0) { + free(b[0]); free(b[1]); free(b[2]); return ((int)bytes); + } memcpy(b[i]+s[i], buff, bytes); s[i] += bytes; if (zip->pack_stream_bytes_unconsumed) @@ -3428,7 +3470,7 @@ skip_stream(struct archive_read *a, size_t skip_bytes) "Truncated 7-Zip file body"); return (ARCHIVE_FATAL); } - bytes -= skipped_bytes; + bytes -= (size_t)skipped_bytes; if (zip->pack_stream_bytes_unconsumed) read_consume(a); } @@ -3506,16 +3548,16 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size) uint32_t dest; for (;;) { uint8_t b; - int index; + int b_index; dest = src - (ip + (uint32_t)bufferPos); if (prevMask == 0) break; - index = kMaskToBitNumber[prevMask] * 8; - b = (uint8_t)(dest >> (24 - index)); + b_index = kMaskToBitNumber[prevMask] * 8; + b = (uint8_t)(dest >> (24 - b_index)); if (!Test86MSByte(b)) break; - src = dest ^ ((1 << (32 - index)) - 1); + src = dest ^ ((1 << (32 - b_index)) - 1); } p[4] = (uint8_t)(~(((dest >> 24) & 1) - 1)); p[3] = (uint8_t)(dest >> 16); @@ -3529,7 +3571,7 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size) } zip->bcj_prevPosT = prevPosT; zip->bcj_prevMask = prevMask; - zip->bcj_ip += bufferPos; + zip->bcj_ip += (uint32_t)bufferPos; return (bufferPos); } @@ -3556,7 +3598,7 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size) #define RC_READ_BYTE (*buffer++) #define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } #define RC_INIT2 zip->bcj2_code = 0; zip->bcj2_range = 0xFFFFFFFF; \ - { int i; for (i = 0; i < 5; i++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }} + { int ii; for (ii = 0; ii < 5; ii++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }} #define NORMALIZE if (zip->bcj2_range < kTopValue) { RC_TEST; zip->bcj2_range <<= 8; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; } @@ -3622,14 +3664,14 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) if (zip->bcj_state == 1) { while (limit != 0) { - uint8_t b = buf0[inPos]; - outBuf[outPos++] = b; - if (IsJ(zip->bcj2_prevByte, b)) { + uint8_t bb = buf0[inPos]; + outBuf[outPos++] = bb; + if (IsJ(zip->bcj2_prevByte, bb)) { zip->bcj_state = 2; break; } inPos++; - zip->bcj2_prevByte = b; + zip->bcj2_prevByte = bb; limit--; } } @@ -3673,7 +3715,7 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) ((uint32_t)v[1] << 16) | ((uint32_t)v[2] << 8) | ((uint32_t)v[3])) - - ((uint32_t)zip->bcj2_outPos + outPos + 4); + ((uint32_t)zip->bcj2_outPos + (uint32_t)outPos + 4); out[0] = (uint8_t)dest; out[1] = (uint8_t)(dest >> 8); out[2] = (uint8_t)(dest >> 16); @@ -3688,7 +3730,7 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) */ zip->odd_bcj_size = 4 -i; for (; i < 4; i++) { - j = i - 4 + zip->odd_bcj_size; + j = i - 4 + (unsigned)zip->odd_bcj_size; zip->odd_bcj[j] = out[i]; } break; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c index 9feb547db..40be18c0c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c @@ -121,6 +121,7 @@ archive_read_support_format_ar(struct archive *_a) archive_read_format_ar_read_header, archive_read_format_ar_read_data, archive_read_format_ar_skip, + NULL, archive_read_format_ar_cleanup); if (r != ARCHIVE_OK) { diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c index e65010e10..4dd38db93 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -292,6 +292,8 @@ struct cab { char end_of_archive; char end_of_entry; char end_of_entry_cleanup; + char read_data_invoked; + int64_t bytes_skipped; unsigned char *uncompressed_buffer; size_t uncompressed_buffer_size; @@ -349,7 +351,7 @@ static int lzx_read_bitlen(struct lzx_stream *, struct huffman *, int); static int lzx_huffman_init(struct huffman *, size_t, int); static void lzx_huffman_free(struct huffman *); static int lzx_make_huffman_table(struct huffman *); -static int inline lzx_decode_huffman(struct huffman *, unsigned); +static inline int lzx_decode_huffman(struct huffman *, unsigned); static int lzx_decode_huffman_tree(struct huffman *, unsigned, int); @@ -380,6 +382,7 @@ archive_read_support_format_cab(struct archive *_a) archive_read_format_cab_read_header, archive_read_format_cab_read_data, archive_read_format_cab_read_data_skip, + NULL, archive_read_format_cab_cleanup); if (r != ARCHIVE_OK) @@ -478,11 +481,13 @@ archive_read_format_cab_options(struct archive_read *a, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "cab: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -535,7 +540,7 @@ truncated_error(struct archive_read *a) return (ARCHIVE_FATAL); } -static int +static ssize_t cab_strnlen(const unsigned char *p, size_t maxlen) { size_t i; @@ -546,7 +551,7 @@ cab_strnlen(const unsigned char *p, size_t maxlen) } if (i > maxlen) return (-1);/* invalid */ - return (i); + return ((ssize_t)i); } /* Read bytes as much as remaining. */ @@ -622,8 +627,9 @@ cab_read_header(struct archive_read *a) struct cab *cab; struct cfheader *hd; size_t bytes, used; + ssize_t len; int64_t skip; - int err, i, len; + int err, i; int cur_folder, prev_folder; uint32_t offset32; @@ -796,7 +802,7 @@ cab_read_header(struct archive_read *a) file->offset = archive_le32dec(p + CFFILE_uoffFolderStart); file->folder = archive_le16dec(p + CFFILE_iFolder); file->mtime = cab_dos_time(p + CFFILE_date_time); - file->attr = archive_le16dec(p + CFFILE_attribs); + file->attr = (uint8_t)archive_le16dec(p + CFFILE_attribs); __archive_read_consume(a, 16); cab->cab_offset += 16; @@ -986,7 +992,7 @@ archive_read_format_cab_read_header(struct archive_read *a, if (file->attr & ATTR_RDONLY) archive_entry_set_mode(entry, AE_IFREG | 0555); else - archive_entry_set_mode(entry, AE_IFREG | 0777); + archive_entry_set_mode(entry, AE_IFREG | 0666); archive_entry_set_mtime(entry, file->mtime, 0); cab->entry_bytes_remaining = file->uncompressed_size; @@ -1024,9 +1030,22 @@ archive_read_format_cab_read_data(struct archive_read *a, default: break; } + if (cab->read_data_invoked == 0) { + if (cab->bytes_skipped) { + if (cab->entry_cfdata == NULL) { + r = cab_next_cfdata(a); + if (r < 0) + return (r); + } + if (cab_consume_cfdata(a, cab->bytes_skipped) < 0) + return (ARCHIVE_FATAL); + cab->bytes_skipped = 0; + } + cab->read_data_invoked = 1; + } if (cab->entry_unconsumed) { /* Consume as much as the compressor actually used. */ - r = cab_consume_cfdata(a, cab->entry_unconsumed); + r = (int)cab_consume_cfdata(a, cab->entry_unconsumed); cab->entry_unconsumed = 0; if (r < 0) return (r); @@ -1049,13 +1068,13 @@ static uint32_t cab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed) { const unsigned char *b; - int u32num; + unsigned u32num; uint32_t sum; - u32num = bytes / 4; + u32num = (unsigned)bytes / 4; sum = seed; b = p; - while (--u32num >= 0) { + for (;u32num > 0; --u32num) { sum ^= archive_le32dec(b); b += 4; } @@ -1356,46 +1375,25 @@ cab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail) struct cab *cab = (struct cab *)(a->format->data); struct cfdata *cfdata; const void *d; - int64_t skipped_bytes; cfdata = cab->entry_cfdata; - if (cfdata->uncompressed_avail == 0 && - cfdata->read_offset > 0) { - /* we've already skipped some bytes before really read. */ - skipped_bytes = cfdata->read_offset; - cfdata->read_offset = 0; - cfdata->uncompressed_bytes_remaining += skipped_bytes; - } else - skipped_bytes = 0; - do { - /* - * Note: '1' here is a performance optimization. - * Recall that the decompression layer returns a count of - * available bytes; asking for more than that forces the - * decompressor to combine reads by copying data. - */ - d = __archive_read_ahead(a, 1, avail); - if (*avail <= 0) { - *avail = truncated_error(a); - return (NULL); - } - if (*avail > cfdata->uncompressed_bytes_remaining) - *avail = cfdata->uncompressed_bytes_remaining; - cfdata->uncompressed_avail = cfdata->uncompressed_size; - cfdata->unconsumed = *avail; - cfdata->sum_ptr = d; - if (skipped_bytes > 0) { - skipped_bytes = - cab_minimum_consume_cfdata(a, skipped_bytes); - if (skipped_bytes < 0) { - *avail = ARCHIVE_FATAL; - return (NULL); - } - continue; - } - } while (0); - + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + d = __archive_read_ahead(a, 1, avail); + if (*avail <= 0) { + *avail = truncated_error(a); + return (NULL); + } + if (*avail > cfdata->uncompressed_bytes_remaining) + *avail = cfdata->uncompressed_bytes_remaining; + cfdata->uncompressed_avail = cfdata->uncompressed_size; + cfdata->unconsumed = *avail; + cfdata->sum_ptr = d; return (d); } @@ -1489,7 +1487,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) * cast to remove 'const'. */ cab->stream.next_in = (Bytef *)(uintptr_t)d; - cab->stream.avail_in = bytes_avail; + cab->stream.avail_in = (uInt)bytes_avail; cab->stream.total_in = 0; /* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */ @@ -1510,7 +1508,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) *avail = ARCHIVE_FATAL; return (NULL); } - mszip -= bytes_avail; + mszip -= (int)bytes_avail; continue; } if (mszip == 1 && cab->stream.next_in[0] != 0x4b) @@ -1541,7 +1539,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) return (NULL); } } - uavail = cab->stream.total_out; + uavail = (uint16_t)cab->stream.total_out; if (uavail < cfdata->uncompressed_size) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -1719,7 +1717,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail) } } - uavail = cab->xstrm.total_out; + uavail = (uint16_t)cab->xstrm.total_out; /* * Make sure a read pointer advances to next CFDATA. */ @@ -1791,9 +1789,8 @@ cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) rbytes -= cbytes; if (cfdata->uncompressed_avail == 0 && - (cab->entry_cffolder->comptype == COMPTYPE_NONE || - cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT || - cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) { + (cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT || + cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) { /* We have not read any data yet. */ if (cbytes == cfdata->uncompressed_bytes_remaining) { /* Skip whole current CFDATA. */ @@ -1819,8 +1816,8 @@ cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) } continue; } - cfdata->read_offset += cbytes; - cfdata->uncompressed_bytes_remaining -= cbytes; + cfdata->read_offset += (uint16_t)cbytes; + cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; break; } else if (cbytes == 0) { err = cab_next_cfdata(a); @@ -1844,7 +1841,7 @@ cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) if (avail <= 0) return (ARCHIVE_FATAL); if (avail > cbytes) - avail = cbytes; + avail = (ssize_t)cbytes; if (cab_minimum_consume_cfdata(a, avail) < 0) return (ARCHIVE_FATAL); cbytes -= avail; @@ -1873,8 +1870,8 @@ cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) else cbytes = cfdata->unconsumed; rbytes -= cbytes; - cfdata->read_offset += cbytes; - cfdata->uncompressed_bytes_remaining -= cbytes; + cfdata->read_offset += (uint16_t)cbytes; + cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; cfdata->unconsumed -= cbytes; } else { cbytes = cfdata->uncompressed_avail - cfdata->read_offset; @@ -1882,8 +1879,8 @@ cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) if (consumed_bytes < cbytes) cbytes = consumed_bytes; rbytes -= cbytes; - cfdata->read_offset += cbytes; - cfdata->uncompressed_bytes_remaining -= cbytes; + cfdata->read_offset += (uint16_t)cbytes; + cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; } if (cfdata->unconsumed) { @@ -1894,12 +1891,12 @@ cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) } if (cbytes) { /* Compute the sum. */ - cab_checksum_update(a, cbytes); + cab_checksum_update(a, (size_t)cbytes); /* Consume as much as the compressor actually used. */ __archive_read_consume(a, cbytes); cab->cab_offset += cbytes; - cfdata->compressed_bytes_remaining -= cbytes; + cfdata->compressed_bytes_remaining -= (uint16_t)cbytes; if (cfdata->compressed_bytes_remaining == 0) { err = cab_checksum_finish(a); if (err < 0) @@ -1940,10 +1937,10 @@ cab_read_data(struct archive_read *a, const void **buff, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA"); return (ARCHIVE_FATAL); } else - return (bytes_avail); + return ((int)bytes_avail); } if (bytes_avail > cab->entry_bytes_remaining) - bytes_avail = cab->entry_bytes_remaining; + bytes_avail = (ssize_t)cab->entry_bytes_remaining; *size = bytes_avail; *offset = cab->entry_offset; @@ -1952,6 +1949,11 @@ cab_read_data(struct archive_read *a, const void **buff, if (cab->entry_bytes_remaining == 0) cab->end_of_entry = 1; cab->entry_unconsumed = bytes_avail; + if (cab->entry_cffolder->comptype == COMPTYPE_NONE) { + /* Don't consume more than current entry used. */ + if (cab->entry_cfdata->unconsumed > cab->entry_unconsumed) + cab->entry_cfdata->unconsumed = cab->entry_unconsumed; + } return (ARCHIVE_OK); } @@ -1967,9 +1969,17 @@ archive_read_format_cab_read_data_skip(struct archive_read *a) if (cab->end_of_archive) return (ARCHIVE_EOF); + if (!cab->read_data_invoked) { + cab->bytes_skipped += cab->entry_bytes_remaining; + cab->entry_bytes_remaining = 0; + /* This entry is finished and done. */ + cab->end_of_entry_cleanup = cab->end_of_entry = 1; + return (ARCHIVE_OK); + } + if (cab->entry_unconsumed) { /* Consume as much as the compressor actually used. */ - r = cab_consume_cfdata(a, cab->entry_unconsumed); + r = (int)cab_consume_cfdata(a, cab->entry_unconsumed); cab->entry_unconsumed = 0; if (r < 0) return (r); @@ -1991,6 +2001,12 @@ archive_read_format_cab_read_data_skip(struct archive_read *a) if (bytes_skipped < 0) return (ARCHIVE_FATAL); + /* If the compression type is none(uncompressed), we've already + * consumed data as much as the current entry size. */ + if (cab->entry_cffolder->comptype == COMPTYPE_NONE && + cab->entry_cfdata != NULL) + cab->entry_cfdata->unconsumed = 0; + /* This entry is finished and done. */ cab->end_of_entry_cleanup = cab->end_of_entry = 1; return (ARCHIVE_OK); @@ -2066,6 +2082,7 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits) struct lzx_dec *ds; int slot, w_size, w_slot; int base, footer; + int base_inc[18]; if (strm->ds == NULL) { strm->ds = calloc(1, sizeof(*strm->ds)); @@ -2100,13 +2117,15 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits) lzx_huffman_free(&(ds->mt)); } + for (footer = 0; footer < 18; footer++) + base_inc[footer] = 1 << footer; base = footer = 0; for (slot = 0; slot < w_slot; slot++) { int n; if (footer == 0) base = slot; else - base += 1 << footer; + base += base_inc[footer]; if (footer < 17) { footer = -2; for (n = base; n; n >>= 1) @@ -2180,11 +2199,11 @@ lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset) end = b + size - 10; while (b < end && (b = memchr(b, 0xE8, end - b)) != NULL) { size_t i = b - (unsigned char *)p; - long cp, displacement, value; + int32_t cp, displacement, value; - cp = offset + i; + cp = (int32_t)(offset + (uint32_t)i); value = archive_le32dec(&b[1]); - if (value >= -cp && value < (long)ds->translation_size) { + if (value >= -cp && value < (int32_t)ds->translation_size) { if (value >= 0) displacement = value - cp; else @@ -2222,7 +2241,9 @@ lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset) /* Notify how many bits we consumed. */ #define lzx_br_consume(br, n) ((br)->cache_avail -= (n)) -#define lzx_br_consume_unalined_bits(br) ((br)->cache_avail &= ~0x0f) +#define lzx_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~0x0f) + +#define lzx_br_is_unaligned(br) ((br)->cache_avail & 0x0f) static const uint32_t cache_masks[] = { 0x00000000, 0x00000001, 0x00000003, 0x00000007, @@ -2349,24 +2370,25 @@ lzx_cleanup_bitstream(struct lzx_stream *strm) #define ST_RD_TRANSLATION_SIZE 1 #define ST_RD_BLOCK_TYPE 2 #define ST_RD_BLOCK_SIZE 3 -#define ST_RD_R0 4 -#define ST_RD_R1 5 -#define ST_RD_R2 6 -#define ST_COPY_UNCOMP1 7 -#define ST_COPY_UNCOMP2 8 -#define ST_RD_ALIGNED_OFFSET 9 -#define ST_RD_VERBATIM 10 -#define ST_RD_PRE_MAIN_TREE_256 11 -#define ST_MAIN_TREE_256 12 -#define ST_RD_PRE_MAIN_TREE_REM 13 -#define ST_MAIN_TREE_REM 14 -#define ST_RD_PRE_LENGTH_TREE 15 -#define ST_LENGTH_TREE 16 -#define ST_MAIN 17 -#define ST_LENGTH 18 -#define ST_OFFSET 19 -#define ST_REAL_POS 20 -#define ST_COPY 21 +#define ST_RD_ALIGNMENT 4 +#define ST_RD_R0 5 +#define ST_RD_R1 6 +#define ST_RD_R2 7 +#define ST_COPY_UNCOMP1 8 +#define ST_COPY_UNCOMP2 9 +#define ST_RD_ALIGNED_OFFSET 10 +#define ST_RD_VERBATIM 11 +#define ST_RD_PRE_MAIN_TREE_256 12 +#define ST_MAIN_TREE_256 13 +#define ST_RD_PRE_MAIN_TREE_REM 14 +#define ST_MAIN_TREE_REM 15 +#define ST_RD_PRE_LENGTH_TREE 16 +#define ST_LENGTH_TREE 17 +#define ST_MAIN 18 +#define ST_LENGTH 19 +#define ST_OFFSET 20 +#define ST_REAL_POS 21 +#define ST_COPY 22 static int lzx_decode(struct lzx_stream *strm, int last) @@ -2470,12 +2492,25 @@ lzx_read_blocks(struct lzx_stream *strm, int last) ds->state = ST_RD_ALIGNED_OFFSET; break; } + /* FALL THROUGH */ + case ST_RD_ALIGNMENT: /* * Handle an Uncompressed Block. */ /* Skip padding to align following field on * 16-bit boundary. */ - lzx_br_consume_unalined_bits(br); + if (lzx_br_is_unaligned(br)) + lzx_br_consume_unaligned_bits(br); + else { + if (lzx_br_read_ahead(strm, br, 16)) + lzx_br_consume(br, 16); + else { + ds->state = ST_RD_ALIGNMENT; + if (last) + goto failed; + return (ARCHIVE_OK); + } + } /* Preparation to read repeated offsets R0,R1 and R2. */ ds->rbytes_avail = 0; ds->state = ST_RD_R0; @@ -2500,8 +2535,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last) lzx_br_consume(br, 16); archive_le16enc(ds->rbytes, u16); ds->rbytes_avail = 2; - } else - ds->rbytes_avail = 0; + } if (ds->rbytes_avail < 4 && ds->br.have_odd) { ds->rbytes[ds->rbytes_avail++] = ds->br.odd; @@ -2517,6 +2551,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last) *strm->next_in++; strm->avail_in--; } + ds->rbytes_avail = 0; if (ds->state == ST_RD_R0) { ds->r0 = archive_le32dec(ds->rbytes); if (ds->r0 < 0) @@ -2541,8 +2576,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last) * Copy bytes form next_in to next_out directly. */ while (ds->block_bytes_avail) { - unsigned char *d; - int l,ll; + int l; if (strm->avail_out <= 0) /* Output buffer is empty. */ @@ -2553,24 +2587,23 @@ lzx_read_blocks(struct lzx_stream *strm, int last) goto failed; return (ARCHIVE_OK); } - l = ds->block_bytes_avail; + l = (int)ds->block_bytes_avail; if (l > ds->w_size - ds->w_pos) l = ds->w_size - ds->w_pos; if (l > strm->avail_out) l = (int)strm->avail_out; if (l > strm->avail_in) l = (int)strm->avail_in; - ll = l; - d = &(ds->w_buff[ds->w_pos]); - while (--l >= 0) { - *strm->next_out++ = *strm->next_in; - *d++ = *strm->next_in++; - } - strm->avail_out -= ll; - strm->total_out += ll; - strm->avail_in -= ll; - ds->w_pos = (ds->w_pos + ll) & ds->w_mask; - ds->block_bytes_avail -= ll; + memcpy(strm->next_out, strm->next_in, l); + memcpy(&(ds->w_buff[ds->w_pos]), + strm->next_in, l); + strm->next_in += l; + strm->avail_in -= l; + strm->next_out += l; + strm->avail_out -= l; + strm->total_out += l; + ds->w_pos = (ds->w_pos + l) & ds->w_mask; + ds->block_bytes_avail -= l; } /* FALL THROUGH */ case ST_COPY_UNCOMP2: @@ -2716,8 +2749,8 @@ lzx_decode_blocks(struct lzx_stream *strm, int last) struct lzx_br bre = ds->br; struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt); const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl; - unsigned char *outp = strm->next_out; - unsigned char *endp = outp + strm->avail_out; + unsigned char *noutp = strm->next_out; + unsigned char *endp = noutp + strm->avail_out; unsigned char *w_buff = ds->w_buff; unsigned char *at_bitlen = at->bitlen; unsigned char *lt_bitlen = lt->bitlen; @@ -2751,10 +2784,10 @@ lzx_decode_blocks(struct lzx_stream *strm, int last) ds->position_slot = position_slot; ds->r0 = r0; ds->r1 = r1; ds->r2 = r2; ds->w_pos = w_pos; - strm->avail_out = endp - outp; + strm->avail_out = endp - noutp; return (ARCHIVE_EOF); } - if (outp >= endp) + if (noutp >= endp) /* Output buffer is empty. */ goto next_data; @@ -2788,7 +2821,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last) w_buff[w_pos] = c; w_pos = (w_pos + 1) & w_mask; /* Store the decoded code to output buffer. */ - *outp++ = c; + *noutp++ = c; block_bytes_avail--; } /* @@ -2933,22 +2966,22 @@ lzx_decode_blocks(struct lzx_stream *strm, int last) if (l > w_size - w_pos) l = w_size - w_pos; } - if (outp + l >= endp) - l = endp - outp; + if (noutp + l >= endp) + l = (int)(endp - noutp); s = w_buff + copy_pos; if (l >= 8 && ((copy_pos + l < w_pos) || (w_pos + l < copy_pos))) { memcpy(w_buff + w_pos, s, l); - memcpy(outp, s, l); + memcpy(noutp, s, l); } else { unsigned char *d; int li; d = w_buff + w_pos; for (li = 0; li < l; li++) - outp[li] = d[li] = s[li]; + noutp[li] = d[li] = s[li]; } - outp += l; + noutp += l; copy_pos = (copy_pos + l) & w_mask; w_pos = (w_pos + l) & w_mask; block_bytes_avail -= l; @@ -2956,7 +2989,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last) /* A copy of current pattern ended. */ break; copy_len -= l; - if (outp >= endp) { + if (noutp >= endp) { /* Output buffer is empty. */ state = ST_COPY; goto next_data; @@ -2979,7 +3012,7 @@ next_data: ds->r0 = r0; ds->r1 = r1; ds->r2 = r2; ds->state = state; ds->w_pos = w_pos; - strm->avail_out = endp - outp; + strm->avail_out = endp - noutp; return (ARCHIVE_OK); } @@ -3096,7 +3129,7 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) hf->bitlen = calloc(len_size, sizeof(hf->bitlen[0])); if (hf->bitlen == NULL) return (ARCHIVE_FATAL); - hf->len_size = len_size; + hf->len_size = (int)len_size; } else memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0])); if (hf->tbl == NULL) { @@ -3104,7 +3137,7 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) bits = tbl_bits; else bits = HTBL_BITS; - hf->tbl = malloc((1 << bits) * sizeof(hf->tbl[0])); + hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0])); if (hf->tbl == NULL) return (ARCHIVE_FATAL); hf->tbl_bits = tbl_bits; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c index 5ae73d770..819f4a4f5 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle - * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -242,6 +242,7 @@ archive_read_support_format_cpio(struct archive *_a) archive_read_format_cpio_read_header, archive_read_format_cpio_read_data, archive_read_format_cpio_skip, + NULL, archive_read_format_cpio_cleanup); if (r != ARCHIVE_OK) @@ -325,7 +326,7 @@ archive_read_format_cpio_options(struct archive_read *a, if (strcmp(key, "compat-2x") == 0) { /* Handle filnames as libarchive 2.x */ cpio->init_default_conversion = (val != NULL)?1:0; - ret = ARCHIVE_OK; + return (ARCHIVE_OK); } else if (strcmp(key, "hdrcharset") == 0) { if (val == NULL || val[0] == 0) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -339,11 +340,13 @@ archive_read_format_cpio_options(struct archive_read *a, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "cpio: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -396,11 +399,12 @@ archive_read_format_cpio_read_header(struct archive_read *a, /* If this is a symlink, read the link contents. */ if (archive_entry_filetype(entry) == AE_IFLNK) { - h = __archive_read_ahead(a, cpio->entry_bytes_remaining, NULL); + h = __archive_read_ahead(a, + (size_t)cpio->entry_bytes_remaining, NULL); if (h == NULL) return (ARCHIVE_FATAL); if (archive_entry_copy_symlink_l(entry, (const char *)h, - cpio->entry_bytes_remaining, sconv) != 0) { + (size_t)cpio->entry_bytes_remaining, sconv) != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Linkname"); @@ -456,7 +460,7 @@ archive_read_format_cpio_read_data(struct archive_read *a, if (bytes_read <= 0) return (ARCHIVE_FATAL); if (bytes_read > cpio->entry_bytes_remaining) - bytes_read = cpio->entry_bytes_remaining; + bytes_read = (ssize_t)cpio->entry_bytes_remaining; *size = bytes_read; cpio->entry_bytes_unconsumed = bytes_read; *offset = cpio->entry_offset; @@ -601,17 +605,23 @@ header_newc(struct archive_read *a, struct cpio *cpio, /* TODO: Abort here? */ } - archive_entry_set_devmajor(entry, atol16(header + newc_devmajor_offset, newc_devmajor_size)); - archive_entry_set_devminor(entry, atol16(header + newc_devminor_offset, newc_devminor_size)); + archive_entry_set_devmajor(entry, + (dev_t)atol16(header + newc_devmajor_offset, newc_devmajor_size)); + archive_entry_set_devminor(entry, + (dev_t)atol16(header + newc_devminor_offset, newc_devminor_size)); archive_entry_set_ino(entry, atol16(header + newc_ino_offset, newc_ino_size)); - archive_entry_set_mode(entry, atol16(header + newc_mode_offset, newc_mode_size)); + archive_entry_set_mode(entry, + (mode_t)atol16(header + newc_mode_offset, newc_mode_size)); archive_entry_set_uid(entry, atol16(header + newc_uid_offset, newc_uid_size)); archive_entry_set_gid(entry, atol16(header + newc_gid_offset, newc_gid_size)); - archive_entry_set_nlink(entry, atol16(header + newc_nlink_offset, newc_nlink_size)); - archive_entry_set_rdevmajor(entry, atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size)); - archive_entry_set_rdevminor(entry, atol16(header + newc_rdevminor_offset, newc_rdevminor_size)); + archive_entry_set_nlink(entry, + (unsigned int)atol16(header + newc_nlink_offset, newc_nlink_size)); + archive_entry_set_rdevmajor(entry, + (dev_t)atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size)); + archive_entry_set_rdevminor(entry, + (dev_t)atol16(header + newc_rdevminor_offset, newc_rdevminor_size)); archive_entry_set_mtime(entry, atol16(header + newc_mtime_offset, newc_mtime_size), 0); - *namelength = atol16(header + newc_namesize_offset, newc_namesize_size); + *namelength = (size_t)atol16(header + newc_namesize_offset, newc_namesize_size); /* Pad name to 2 more than a multiple of 4. */ *name_pad = (2 - *namelength) & 3; @@ -765,15 +775,19 @@ header_odc(struct archive_read *a, struct cpio *cpio, /* Parse out octal fields. */ header = (const char *)h; - archive_entry_set_dev(entry, atol8(header + odc_dev_offset, odc_dev_size)); + archive_entry_set_dev(entry, + (dev_t)atol8(header + odc_dev_offset, odc_dev_size)); archive_entry_set_ino(entry, atol8(header + odc_ino_offset, odc_ino_size)); - archive_entry_set_mode(entry, atol8(header + odc_mode_offset, odc_mode_size)); + archive_entry_set_mode(entry, + (mode_t)atol8(header + odc_mode_offset, odc_mode_size)); archive_entry_set_uid(entry, atol8(header + odc_uid_offset, odc_uid_size)); archive_entry_set_gid(entry, atol8(header + odc_gid_offset, odc_gid_size)); - archive_entry_set_nlink(entry, atol8(header + odc_nlink_offset, odc_nlink_size)); - archive_entry_set_rdev(entry, atol8(header + odc_rdev_offset, odc_rdev_size)); + archive_entry_set_nlink(entry, + (unsigned int)atol8(header + odc_nlink_offset, odc_nlink_size)); + archive_entry_set_rdev(entry, + (dev_t)atol8(header + odc_rdev_offset, odc_rdev_size)); archive_entry_set_mtime(entry, atol8(header + odc_mtime_offset, odc_mtime_size), 0); - *namelength = atol8(header + odc_namesize_offset, odc_namesize_size); + *namelength = (size_t)atol8(header + odc_namesize_offset, odc_namesize_size); *name_pad = 0; /* No padding of filename. */ /* @@ -814,15 +828,19 @@ header_afiol(struct archive_read *a, struct cpio *cpio, /* Parse out octal fields. */ header = (const char *)h; - archive_entry_set_dev(entry, atol16(header + afiol_dev_offset, afiol_dev_size)); + archive_entry_set_dev(entry, + (dev_t)atol16(header + afiol_dev_offset, afiol_dev_size)); archive_entry_set_ino(entry, atol16(header + afiol_ino_offset, afiol_ino_size)); - archive_entry_set_mode(entry, atol8(header + afiol_mode_offset, afiol_mode_size)); + archive_entry_set_mode(entry, + (mode_t)atol8(header + afiol_mode_offset, afiol_mode_size)); archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size)); archive_entry_set_gid(entry, atol16(header + afiol_gid_offset, afiol_gid_size)); - archive_entry_set_nlink(entry, atol16(header + afiol_nlink_offset, afiol_nlink_size)); - archive_entry_set_rdev(entry, atol16(header + afiol_rdev_offset, afiol_rdev_size)); + archive_entry_set_nlink(entry, + (unsigned int)atol16(header + afiol_nlink_offset, afiol_nlink_size)); + archive_entry_set_rdev(entry, + (dev_t)atol16(header + afiol_rdev_offset, afiol_rdev_size)); archive_entry_set_mtime(entry, atol16(header + afiol_mtime_offset, afiol_mtime_size), 0); - *namelength = atol16(header + afiol_namesize_offset, afiol_namesize_size); + *namelength = (size_t)atol16(header + afiol_namesize_offset, afiol_namesize_size); *name_pad = 0; /* No padding of filename. */ cpio->entry_bytes_remaining = diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c index 3dc2196cb..366073820 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c @@ -53,6 +53,7 @@ archive_read_support_format_empty(struct archive *_a) archive_read_format_empty_read_header, archive_read_format_empty_read_data, NULL, + NULL, NULL); return (r); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c index db7aa9d9b..8147461b9 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2009 Andreas Henriksson <andreas@fatal.se> - * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -374,6 +374,8 @@ struct iso9660 { size_t utf16be_path_len; unsigned char *utf16be_previous_path; size_t utf16be_previous_path_len; + /* Null buufer used in bidder to improve its performance. */ + unsigned char null[2048]; }; static int archive_read_format_iso9660_bid(struct archive_read *, int); @@ -475,6 +477,7 @@ archive_read_support_format_iso9660(struct archive *_a) archive_read_format_iso9660_read_header, archive_read_format_iso9660_read_data, archive_read_format_iso9660_read_data_skip, + NULL, archive_read_format_iso9660_cleanup); if (r != ARCHIVE_OK) { @@ -588,6 +591,23 @@ archive_read_format_iso9660_options(struct archive_read *a, } static int +isNull(struct iso9660 *iso9660, const unsigned char *h, unsigned offset, +unsigned bytes) +{ + + while (bytes >= sizeof(iso9660->null)) { + if (!memcmp(iso9660->null, h + offset, sizeof(iso9660->null))) + return (0); + offset += sizeof(iso9660->null); + bytes -= sizeof(iso9660->null); + } + if (bytes) + return memcmp(iso9660->null, h + offset, bytes) == 0; + else + return (1); +} + +static int isBootRecord(struct iso9660 *iso9660, const unsigned char *h) { (void)iso9660; /* UNUSED */ @@ -632,8 +652,6 @@ isVolumePartition(struct iso9660 *iso9660, const unsigned char *h) static int isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h) { - int i; - (void)iso9660; /* UNUSED */ /* Type of the Volume Descriptor Set Terminator must be 255. */ @@ -645,9 +663,8 @@ isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h) return (0); /* Reserved field must be 0. */ - for (i = 7; i < 2048; ++i) - if (h[i] != 0) - return (0); + if (!isNull(iso9660, h, 7, 2048-7)) + return (0); return (1); } @@ -708,7 +725,6 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h) ssize_t logical_block_size; int32_t volume_block; int32_t location; - int i; (void)iso9660; /* UNUSED */ @@ -717,15 +733,12 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h) return (0); /* Reserved field must be 0. */ - for (i = 0; i < SVD_reserved1_size; ++i) - if (h[SVD_reserved1_offset + i] != 0) - return (0); - for (i = 0; i < SVD_reserved2_size; ++i) - if (h[SVD_reserved2_offset + i] != 0) - return (0); - for (i = 0; i < SVD_reserved3_size; ++i) - if (h[SVD_reserved3_offset + i] != 0) - return (0); + if (!isNull(iso9660, h, SVD_reserved1_offset, SVD_reserved1_size)) + return (0); + if (!isNull(iso9660, h, SVD_reserved2_offset, SVD_reserved2_size)) + return (0); + if (!isNull(iso9660, h, SVD_reserved3_offset, SVD_reserved3_size)) + return (0); /* File structure version must be 1 for ISO9660/ECMA119. */ if (h[SVD_file_structure_version_offset] != 1) @@ -771,7 +784,6 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h) ssize_t logical_block_size; int32_t volume_block; int32_t location; - int i; (void)iso9660; /* UNUSED */ @@ -788,14 +800,12 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h) return (0); /* Reserved field must be 0. */ - for (i = 0; i < PVD_reserved2_size; ++i) - if (h[PVD_reserved2_offset + i] != 0) - return (0); + if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size)) + return (0); /* Reserved field must be 0. */ - for (i = 0; i < PVD_reserved3_size; ++i) - if (h[PVD_reserved3_offset + i] != 0) - return (0); + if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size)) + return (0); /* Logical block size must be > 0. */ /* I've looked at Ecma 119 and can't find any stronger @@ -830,14 +840,12 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h) return (0); /* Reserved field must be 0. */ - for (i = 0; i < PVD_reserved4_size; ++i) - if (h[PVD_reserved4_offset + i] != 0) - return (0); + if (!isNull(iso9660, h, PVD_reserved4_offset, PVD_reserved4_size)) + return (0); /* Reserved field must be 0. */ - for (i = 0; i < PVD_reserved5_size; ++i) - if (h[PVD_reserved5_offset + i] != 0) - return (0); + if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size)) + return (0); /* Read Root Directory Record in Volume Descriptor. */ p = h + PVD_root_directory_record_offset; @@ -869,14 +877,12 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h) return (0); /* Reserved field must be 0. */ - for (i = 0; i < PVD_reserved2_size; ++i) - if (h[PVD_reserved2_offset + i] != 0) - return (0); + if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size)) + return (0); /* Reserved field must be 0. */ - for (i = 0; i < PVD_reserved3_size; ++i) - if (h[PVD_reserved3_offset + i] != 0) - return (0); + if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size)) + return (0); /* Logical block size must be > 0. */ /* I've looked at Ecma 119 and can't find any stronger @@ -919,9 +925,8 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h) return (0); /* Reserved field must be 0. */ - for (i = 0; i < PVD_reserved5_size; ++i) - if (h[PVD_reserved5_offset + i] != 0) - return (0); + if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size)) + return (0); /* XXX TODO: Check other values for sanity; reject more * malformed PVDs. XXX */ @@ -934,8 +939,10 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h) if (!iso9660->primary.location) { iso9660->logical_block_size = logical_block_size; iso9660->volume_block = volume_block; - iso9660->volume_size = logical_block_size * (uint64_t)volume_block; - iso9660->primary.location = archive_le32dec(p + DR_extent_offset); + iso9660->volume_size = + logical_block_size * (uint64_t)volume_block; + iso9660->primary.location = + archive_le32dec(p + DR_extent_offset); iso9660->primary.size = archive_le32dec(p + DR_size_offset); } @@ -951,6 +958,12 @@ read_children(struct archive_read *a, struct file_info *parent) size_t step, skip_size; iso9660 = (struct iso9660 *)(a->format->data); + /* flush any remaining bytes from the last round to ensure + * we're positioned */ + if (iso9660->entry_bytes_unconsumed) { + __archive_read_consume(a, iso9660->entry_bytes_unconsumed); + iso9660->entry_bytes_unconsumed = 0; + } if (iso9660->current_position > parent->offset) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Ignoring out-of-order directory (%s) %jd > %jd", @@ -975,8 +988,8 @@ read_children(struct archive_read *a, struct file_info *parent) iso9660->current_position = parent->offset; } - step = ((parent->size + iso9660->logical_block_size -1) / - iso9660->logical_block_size) * iso9660->logical_block_size; + step = (size_t)(((parent->size + iso9660->logical_block_size -1) / + iso9660->logical_block_size) * iso9660->logical_block_size); b = __archive_read_ahead(a, step, NULL); if (b == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -1060,101 +1073,112 @@ read_children(struct archive_read *a, struct file_info *parent) } static int -archive_read_format_iso9660_read_header(struct archive_read *a, - struct archive_entry *entry) +choose_volume(struct archive_read *a, struct iso9660 *iso9660) { - struct iso9660 *iso9660; struct file_info *file; - int r, rd_r = ARCHIVE_OK; - - iso9660 = (struct iso9660 *)(a->format->data); + int64_t skipsize; + struct vd *vd; + const void *block; + char seenJoliet; - if (!a->archive.archive_format) { - a->archive.archive_format = ARCHIVE_FORMAT_ISO9660; - a->archive.archive_format_name = "ISO9660"; + vd = &(iso9660->primary); + if (!iso9660->opt_support_joliet) + iso9660->seenJoliet = 0; + if (iso9660->seenJoliet && + vd->location > iso9660->joliet.location) + /* This condition is unlikely; by way of caution. */ + vd = &(iso9660->joliet); + + skipsize = LOGICAL_BLOCK_SIZE * vd->location; + skipsize = __archive_read_consume(a, skipsize); + if (skipsize < 0) + return ((int)skipsize); + iso9660->current_position = skipsize; + + block = __archive_read_ahead(a, vd->size, NULL); + if (block == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to read full block when scanning " + "ISO9660 directory list"); + return (ARCHIVE_FATAL); } - if (iso9660->current_position == 0) { - int64_t skipsize; - struct vd *vd; - const void *block; - char seenJoliet; - - vd = &(iso9660->primary); - if (!iso9660->opt_support_joliet) - iso9660->seenJoliet = 0; - if (iso9660->seenJoliet && - vd->location > iso9660->joliet.location) - /* This condition is unlikely; by way of caution. */ - vd = &(iso9660->joliet); + /* + * While reading Root Directory, flag seenJoliet must be zero to + * avoid converting special name 0x00(Current Directory) and + * next byte to UCS2. + */ + seenJoliet = iso9660->seenJoliet;/* Save flag. */ + iso9660->seenJoliet = 0; + file = parse_file_info(a, NULL, block); + if (file == NULL) + return (ARCHIVE_FATAL); + iso9660->seenJoliet = seenJoliet; + /* + * If the iso image has both RockRidge and Joliet, we preferentially + * use RockRidge Extensions rather than Joliet ones. + */ + if (vd == &(iso9660->primary) && iso9660->seenRockridge + && iso9660->seenJoliet) + iso9660->seenJoliet = 0; + + if (vd == &(iso9660->primary) && !iso9660->seenRockridge + && iso9660->seenJoliet) { + /* Switch reading data from primary to joliet. */ + vd = &(iso9660->joliet); skipsize = LOGICAL_BLOCK_SIZE * vd->location; + skipsize -= iso9660->current_position; skipsize = __archive_read_consume(a, skipsize); if (skipsize < 0) return ((int)skipsize); - iso9660->current_position = skipsize; + iso9660->current_position += skipsize; block = __archive_read_ahead(a, vd->size, NULL); if (block == NULL) { - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Failed to read full block when scanning " "ISO9660 directory list"); return (ARCHIVE_FATAL); } - - /* - * While reading Root Directory, flag seenJoliet - * must be zero to avoid converting special name - * 0x00(Current Directory) and next byte to UCS2. - */ - seenJoliet = iso9660->seenJoliet;/* Save flag. */ iso9660->seenJoliet = 0; file = parse_file_info(a, NULL, block); if (file == NULL) return (ARCHIVE_FATAL); iso9660->seenJoliet = seenJoliet; - if (vd == &(iso9660->primary) && iso9660->seenRockridge - && iso9660->seenJoliet) - /* - * If iso image has RockRidge and Joliet, - * we use RockRidge Extensions. - */ - iso9660->seenJoliet = 0; - if (vd == &(iso9660->primary) && !iso9660->seenRockridge - && iso9660->seenJoliet) { - /* Switch reading data from primary to joliet. */ - vd = &(iso9660->joliet); - skipsize = LOGICAL_BLOCK_SIZE * vd->location; - skipsize -= iso9660->current_position; - skipsize = __archive_read_consume(a, skipsize); - if (skipsize < 0) - return ((int)skipsize); - iso9660->current_position += skipsize; - - block = __archive_read_ahead(a, vd->size, NULL); - if (block == NULL) { - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "Failed to read full block when scanning " - "ISO9660 directory list"); - return (ARCHIVE_FATAL); - } - iso9660->seenJoliet = 0; - file = parse_file_info(a, NULL, block); - if (file == NULL) - return (ARCHIVE_FATAL); - iso9660->seenJoliet = seenJoliet; - } - /* Store the root directory in the pending list. */ - if (add_entry(a, iso9660, file) != ARCHIVE_OK) - return (ARCHIVE_FATAL); - if (iso9660->seenRockridge) { - a->archive.archive_format = - ARCHIVE_FORMAT_ISO9660_ROCKRIDGE; - a->archive.archive_format_name = - "ISO9660 with Rockridge extensions"; - } + } + + /* Store the root directory in the pending list. */ + if (add_entry(a, iso9660, file) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if (iso9660->seenRockridge) { + a->archive.archive_format = ARCHIVE_FORMAT_ISO9660_ROCKRIDGE; + a->archive.archive_format_name = + "ISO9660 with Rockridge extensions"; + } + + return (ARCHIVE_OK); +} + +static int +archive_read_format_iso9660_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct iso9660 *iso9660; + struct file_info *file; + int r, rd_r = ARCHIVE_OK; + + iso9660 = (struct iso9660 *)(a->format->data); + + if (!a->archive.archive_format) { + a->archive.archive_format = ARCHIVE_FORMAT_ISO9660; + a->archive.archive_format_name = "ISO9660"; + } + + if (iso9660->current_position == 0) { + r = choose_volume(a, iso9660); + if (r != ARCHIVE_OK) + return (r); } file = NULL;/* Eliminate a warning. */ @@ -1227,14 +1251,14 @@ archive_read_format_iso9660_read_header(struct archive_read *a, } iso9660->entry_bytes_remaining = file->size; - iso9660->entry_sparse_offset = 0; /* Offset for sparse-file-aware clients. */ + /* Offset for sparse-file-aware clients. */ + iso9660->entry_sparse_offset = 0; if (file->offset + file->size > iso9660->volume_size) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "File is beyond end-of-media: %s", archive_entry_pathname(entry)); iso9660->entry_bytes_remaining = 0; - iso9660->entry_sparse_offset = 0; return (ARCHIVE_WARN); } @@ -1286,36 +1310,33 @@ archive_read_format_iso9660_read_header(struct archive_read *a, iso9660->previous_pathname.s); archive_entry_unset_size(entry); iso9660->entry_bytes_remaining = 0; - iso9660->entry_sparse_offset = 0; return (rd_r); } - /* Except for the hardlink case above, if the offset of the - * next entry is before our current position, we can't seek - * backwards to extract it, so issue a warning. Note that - * this can only happen if this entry was added to the heap - * after we passed this offset, that is, only if the directory - * mentioning this entry is later than the body of the entry. - * Such layouts are very unusual; most ISO9660 writers lay out - * and record all directory information first, then store - * all file bodies. */ - /* TODO: Someday, libarchive's I/O core will support optional - * seeking. When that day comes, this code should attempt to - * seek and only return the error if the seek fails. That - * will give us support for whacky ISO images that require - * seeking while retaining the ability to read almost all ISO - * images in a streaming fashion. */ if ((file->mode & AE_IFMT) != AE_IFDIR && file->offset < iso9660->current_position) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Ignoring out-of-order file @%jx (%s) %jd < %jd", - (intmax_t)file->number, - iso9660->pathname.s, - (intmax_t)file->offset, - (intmax_t)iso9660->current_position); - iso9660->entry_bytes_remaining = 0; - iso9660->entry_sparse_offset = 0; - return (ARCHIVE_WARN); + int64_t r64; + + r64 = __archive_read_seek(a, file->offset, SEEK_SET); + if (r64 != (int64_t)file->offset) { + /* We can't seek backwards to extract it, so issue + * a warning. Note that this can only happen if + * this entry was added to the heap after we passed + * this offset, that is, only if the directory + * mentioning this entry is later than the body of + * the entry. Such layouts are very unusual; most + * ISO9660 writers lay out and record all directory + * information first, then store all file bodies. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignoring out-of-order file @%jx (%s) %jd < %jd", + (intmax_t)file->number, + iso9660->pathname.s, + (intmax_t)file->offset, + (intmax_t)iso9660->current_position); + iso9660->entry_bytes_remaining = 0; + return (ARCHIVE_WARN); + } + iso9660->current_position = (uint64_t)r64; } /* Initialize zisofs variables. */ @@ -1356,7 +1377,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a, archive_entry_set_nlink(entry, 2 + file->subdirs); /* Directory data has been read completely. */ iso9660->entry_bytes_remaining = 0; - iso9660->entry_sparse_offset = 0; } if (rd_r != ARCHIVE_OK) @@ -1397,7 +1417,7 @@ zisofs_read_data(struct archive_read *a, return (ARCHIVE_FATAL); } if (bytes_read > iso9660->entry_bytes_remaining) - bytes_read = iso9660->entry_bytes_remaining; + bytes_read = (ssize_t)iso9660->entry_bytes_remaining; avail = bytes_read; uncompressed_size = 0; @@ -1405,9 +1425,9 @@ zisofs_read_data(struct archive_read *a, size_t ceil, xsize; /* Allocate block pointers buffer. */ - ceil = (zisofs->pz_uncompressed_size + + ceil = (size_t)((zisofs->pz_uncompressed_size + (((int64_t)1) << zisofs->pz_log2_bs) - 1) - >> zisofs->pz_log2_bs; + >> zisofs->pz_log2_bs); xsize = (ceil + 1) * 4; if (zisofs->block_pointers_alloc < xsize) { size_t alloc; @@ -1426,7 +1446,7 @@ zisofs_read_data(struct archive_read *a, zisofs->block_pointers_size = xsize; /* Allocate uncompressed data buffer. */ - xsize = 1UL << zisofs->pz_log2_bs; + xsize = (size_t)1UL << zisofs->pz_log2_bs; if (zisofs->uncompressed_buffer_size < xsize) { if (zisofs->uncompressed_buffer != NULL) free(zisofs->uncompressed_buffer); @@ -1563,9 +1583,10 @@ zisofs_read_data(struct archive_read *a, if (avail > zisofs->block_avail) zisofs->stream.avail_in = zisofs->block_avail; else - zisofs->stream.avail_in = avail; + zisofs->stream.avail_in = (uInt)avail; zisofs->stream.next_out = zisofs->uncompressed_buffer; - zisofs->stream.avail_out = zisofs->uncompressed_buffer_size; + zisofs->stream.avail_out = + (uInt)zisofs->uncompressed_buffer_size; r = inflate(&zisofs->stream, 0); switch (r) { @@ -1580,7 +1601,7 @@ zisofs_read_data(struct archive_read *a, uncompressed_size = zisofs->uncompressed_buffer_size - zisofs->stream.avail_out; avail -= zisofs->stream.next_in - p; - zisofs->block_avail -= zisofs->stream.next_in - p; + zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p); } next_data: bytes_read -= avail; @@ -1590,7 +1611,7 @@ next_data: iso9660->entry_sparse_offset += uncompressed_size; iso9660->entry_bytes_remaining -= bytes_read; iso9660->current_position += bytes_read; - zisofs->pz_offset += bytes_read; + zisofs->pz_offset += (uint32_t)bytes_read; iso9660->entry_bytes_unconsumed += bytes_read; return (ARCHIVE_OK); @@ -1671,7 +1692,7 @@ archive_read_format_iso9660_read_data(struct archive_read *a, if (*buff == NULL) return (ARCHIVE_FATAL); if (bytes_read > iso9660->entry_bytes_remaining) - bytes_read = iso9660->entry_bytes_remaining; + bytes_read = (ssize_t)iso9660->entry_bytes_remaining; *size = bytes_read; *offset = iso9660->entry_sparse_offset; iso9660->entry_sparse_offset += bytes_read; @@ -1756,7 +1777,8 @@ parse_file_info(struct archive_read *a, struct file_info *parent, */ if (location > 0 && (location + ((fsize + iso9660->logical_block_size -1) - / iso9660->logical_block_size)) > iso9660->volume_block) { + / iso9660->logical_block_size)) + > (uint32_t)iso9660->volume_block) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid location of extent of file"); return (NULL); @@ -1872,9 +1894,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, if (iso9660->opt_support_rockridge) { if (parent == NULL && rr_end - rr_start >= 7) { p = rr_start; - if (p[0] == 'S' && p[1] == 'P' - && p[2] == 7 && p[3] == 1 - && p[4] == 0xBE && p[5] == 0xEF) { + if (memcmp(p, "SP\x07\x01\xbe\xef", 6) == 0) { /* * SP extension stores the suspOffset * (Number of bytes to skip between @@ -1907,6 +1927,19 @@ parse_file_info(struct archive_read *a, struct file_info *parent, free(file); return (NULL); } + /* + * A file size of symbolic link files in ISO images + * made by makefs is not zero and its location is + * the same as those of next regular file. That is + * the same as hard like file and it causes unexpected + * error. + */ + if (file->size > 0 && + (file->mode & AE_IFMT) == AE_IFLNK) { + file->size = 0; + file->number = -1; + file->offset = -1; + } } else /* If there isn't SUSP, disable parsing * rock ridge extensions. */ @@ -1921,6 +1954,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, if (iso9660->seenRockridge) { if (parent != NULL && parent->parent == NULL && (flags & 0x02) && iso9660->rr_moved == NULL && + file->name.s && (strcmp(file->name.s, "rr_moved") == 0 || strcmp(file->name.s, ".rr_moved") == 0)) { iso9660->rr_moved = file; @@ -2053,14 +2087,9 @@ parse_rockridge(struct archive_read *a, struct file_info *file, int data_length = p[2] - 4; int version = p[3]; - /* - * Yes, each 'if' here does test p[0] again. - * Otherwise, the fall-through handling to catch - * unsupported extensions doesn't work. - */ switch(p[0]) { case 'C': - if (p[0] == 'C' && p[1] == 'E') { + if (p[1] == 'E') { if (version == 1 && data_length == 24) { /* * CE extension comprises: @@ -2078,53 +2107,42 @@ parse_rockridge(struct archive_read *a, struct file_info *file, != ARCHIVE_OK) return (ARCHIVE_FATAL); } - break; } - if (p[0] == 'C' && p[1] == 'L') { + else if (p[1] == 'L') { if (version == 1 && data_length == 8) { file->cl_offset = (uint64_t) iso9660->logical_block_size * (uint64_t)archive_le32dec(data); iso9660->seenRockridge = 1; } - break; } - /* FALLTHROUGH */ + break; case 'N': - if (p[0] == 'N' && p[1] == 'M') { + if (p[1] == 'M') { if (version == 1) { parse_rockridge_NM1(file, data, data_length); iso9660->seenRockridge = 1; } - break; } - /* FALLTHROUGH */ + break; case 'P': - if (p[0] == 'P' && p[1] == 'D') { - /* - * PD extension is padding; - * contents are always ignored. - */ - break; - } - if (p[0] == 'P' && p[1] == 'L') { - /* - * PL extension won't appear; - * contents are always ignored. - */ - break; - } - if (p[0] == 'P' && p[1] == 'N') { + /* + * PD extension is padding; + * contents are always ignored. + * + * PL extension won't appear; + * contents are always ignored. + */ + if (p[1] == 'N') { if (version == 1 && data_length == 16) { file->rdev = toi(data,4); file->rdev <<= 32; file->rdev |= toi(data + 8, 4); iso9660->seenRockridge = 1; } - break; } - if (p[0] == 'P' && p[1] == 'X') { + else if (p[1] == 'X') { /* * PX extension comprises: * 8 bytes for mode, @@ -2151,35 +2169,31 @@ parse_rockridge(struct archive_read *a, struct file_info *file, = toi(data + 32, 4); iso9660->seenRockridge = 1; } - break; } - /* FALLTHROUGH */ + break; case 'R': - if (p[0] == 'R' && p[1] == 'E' && version == 1) { + if (p[1] == 'E' && version == 1) { file->re = 1; iso9660->seenRockridge = 1; - break; } - if (p[0] == 'R' && p[1] == 'R' && version == 1) { + else if (p[1] == 'R' && version == 1) { /* * RR extension comprises: * one byte flag value * This extension is obsolete, * so contents are always ignored. */ - break; } - /* FALLTHROUGH */ + break; case 'S': - if (p[0] == 'S' && p[1] == 'L') { + if (p[1] == 'L') { if (version == 1) { parse_rockridge_SL1(file, data, data_length); iso9660->seenRockridge = 1; } - break; } - if (p[0] == 'S' && p[1] == 'T' + else if (p[1] == 'T' && data_length == 0 && version == 1) { /* * ST extension marks end of this @@ -2194,32 +2208,27 @@ parse_rockridge(struct archive_read *a, struct file_info *file, iso9660->seenRockridge = 0; return (ARCHIVE_OK); } + break; case 'T': - if (p[0] == 'T' && p[1] == 'F') { + if (p[1] == 'F') { if (version == 1) { parse_rockridge_TF1(file, data, data_length); iso9660->seenRockridge = 1; } - break; } - /* FALLTHROUGH */ + break; case 'Z': - if (p[0] == 'Z' && p[1] == 'F') { + if (p[1] == 'F') { if (version == 1) parse_rockridge_ZF1(file, data, data_length); - break; } - /* FALLTHROUGH */ + break; default: - /* The FALLTHROUGHs above leave us here for - * any unsupported extension. */ break; } - - p += p[2]; } return (ARCHIVE_OK); @@ -2241,7 +2250,7 @@ register_CE(struct archive_read *a, int32_t location, offset >= file->offset) || offset < iso9660->current_position || (((uint64_t)file->ce_offset) + file->ce_size) - > iso9660->logical_block_size || + > (uint64_t)iso9660->logical_block_size || offset + file->ce_offset + file->ce_size > iso9660->volume_size) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -2263,7 +2272,7 @@ register_CE(struct archive_read *a, int32_t location, archive_set_error(&a->archive, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); } - p = malloc(new_size * sizeof(p[0])); + p = calloc(new_size, sizeof(p[0])); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); @@ -2513,9 +2522,6 @@ parse_rockridge_SL1(struct file_info *file, const unsigned char *data, if (!file->symlink_continues || file->symlink.length < 1) archive_string_empty(&file->symlink); - else if (!file->symlink_continues && - file->symlink.s[file->symlink.length - 1] != '/') - separator = "/"; file->symlink_continues = 0; /* @@ -2882,8 +2888,9 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660, fatal_rr: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Failed to connect 'CL' pointer to 'RE' rr_moved pointer of" - "Rockridge extensions"); + "Failed to connect 'CL' pointer to 'RE' rr_moved pointer of " + "Rockridge extensions: current position = %jd, CL offset = %jd", + (intmax_t)iso9660->current_position, (intmax_t)file->cl_offset); return (ARCHIVE_FATAL); } @@ -3085,6 +3092,8 @@ isodate7(const unsigned char *v) { struct tm tm; int offset; + time_t t; + memset(&tm, 0, sizeof(tm)); tm.tm_year = v[0]; tm.tm_mon = v[1] - 1; @@ -3098,7 +3107,10 @@ isodate7(const unsigned char *v) tm.tm_hour -= offset / 4; tm.tm_min -= (offset % 4) * 15; } - return (time_from_tm(&tm)); + t = time_from_tm(&tm); + if (t == (time_t)-1) + return ((time_t)0); + return (t); } static time_t @@ -3106,6 +3118,8 @@ isodate17(const unsigned char *v) { struct tm tm; int offset; + time_t t; + memset(&tm, 0, sizeof(tm)); tm.tm_year = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + (v[2] - '0') * 10 + (v[3] - '0') @@ -3121,7 +3135,10 @@ isodate17(const unsigned char *v) tm.tm_hour -= offset / 4; tm.tm_min -= (offset % 4) * 15; } - return (time_from_tm(&tm)); + t = time_from_tm(&tm); + if (t == (time_t)-1) + return ((time_t)0); + return (t); } static time_t @@ -3135,7 +3152,8 @@ time_from_tm(struct tm *t) #else /* Else use direct calculation using POSIX assumptions. */ /* First, fix up tm_yday based on the year/month/day. */ - mktime(t); + if (mktime(t) == (time_t)-1) + return ((time_t)-1); /* Then we can compute timegm() from first principles. */ return (t->tm_sec + t->tm_min * 60 + t->tm_hour * 3600 + t->tm_yday * 86400 + (t->tm_year - 70) * 31536000 @@ -3204,10 +3222,12 @@ dump_isodirrec(FILE *out, const unsigned char *isodirrec) fprintf(out, " ilv %d,", toi(isodirrec + DR_interleave_offset, DR_interleave_size)); fprintf(out, " seq %d,", - toi(isodirrec + DR_volume_sequence_number_offset, DR_volume_sequence_number_size)); + toi(isodirrec + DR_volume_sequence_number_offset, + DR_volume_sequence_number_size)); fprintf(out, " nl %d:", toi(isodirrec + DR_name_len_offset, DR_name_len_size)); fprintf(out, " `%.*s'", - toi(isodirrec + DR_name_len_offset, DR_name_len_size), isodirrec + DR_name_offset); + toi(isodirrec + DR_name_len_offset, DR_name_len_size), + isodirrec + DR_name_offset); } #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c index 50256b161..f702949fb 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2011 Michihiro NAKAJIMA + * Copyright (c) 2008-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -272,7 +272,7 @@ static int lha_skip_sfx(struct archive_read *); static time_t lha_dos_time(const unsigned char *); static time_t lha_win_time(uint64_t, long *); static unsigned char lha_calcsum(unsigned char, const void *, - int, int); + int, size_t); static int lha_parse_linkname(struct archive_string *, struct archive_string *); static int lha_read_data_none(struct archive_read *, const void **, @@ -289,7 +289,7 @@ static void lzh_huffman_free(struct huffman *); static int lzh_read_pt_bitlen(struct lzh_stream *, int start, int end); static int lzh_make_fake_table(struct huffman *, uint16_t); static int lzh_make_huffman_table(struct huffman *); -static int inline lzh_decode_huffman(struct huffman *, unsigned); +static inline int lzh_decode_huffman(struct huffman *, unsigned); static int lzh_decode_huffman_tree(struct huffman *, unsigned, int); @@ -319,6 +319,7 @@ archive_read_support_format_lha(struct archive *_a) archive_read_format_lha_read_header, archive_read_format_lha_read_data, archive_read_format_lha_read_data_skip, + NULL, archive_read_format_lha_cleanup); if (r != ARCHIVE_OK) @@ -445,11 +446,13 @@ archive_read_format_lha_options(struct archive_read *a, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "lha: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -696,7 +699,7 @@ archive_read_format_lha_read_header(struct archive_read *a, archive_entry_set_symlink(entry, NULL); archive_string_free(&linkname); /* - * When a header level is 0, there is a possibilty that + * When a header level is 0, there is a possibility that * a pathname and a symlink has '\' character, a directory * separator in DOS/Windows. So we should convert it to '/'. */ @@ -949,7 +952,7 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha) /* Read extended headers */ err2 = lha_read_file_extended_header(a, lha, NULL, 2, - lha->compsize + 2, &extdsize); + (size_t)(lha->compsize + 2), &extdsize); if (err2 < ARCHIVE_WARN) return (err2); if (err2 < err) @@ -1444,7 +1447,7 @@ lha_read_data_none(struct archive_read *a, const void **buff, return (ARCHIVE_FATAL); } if (bytes_avail > lha->entry_bytes_remaining) - bytes_avail = lha->entry_bytes_remaining; + bytes_avail = (ssize_t)lha->entry_bytes_remaining; lha->entry_crc_calculated = lha_crc16(lha->entry_crc_calculated, *buff, bytes_avail); *size = bytes_avail; @@ -1527,7 +1530,7 @@ lha_read_data_lzh(struct archive_read *a, const void **buff, return (ARCHIVE_FATAL); } if (bytes_avail > lha->entry_bytes_remaining) - bytes_avail = lha->entry_bytes_remaining; + bytes_avail = (ssize_t)lha->entry_bytes_remaining; lha->strm.avail_in = bytes_avail; lha->strm.total_in = 0; @@ -1573,7 +1576,7 @@ static int archive_read_format_lha_read_data_skip(struct archive_read *a) { struct lha *lha; - off_t bytes_skipped; + int64_t bytes_skipped; lha = (struct lha *)(a->format->data); @@ -1632,7 +1635,7 @@ lha_parse_linkname(struct archive_string *linkname, struct archive_string *pathname) { char * linkptr; - int symlen; + size_t symlen; linkptr = strchr(pathname->s, '|'); if (linkptr != NULL) { @@ -1687,12 +1690,12 @@ lha_win_time(uint64_t wintime, long *ns) } static unsigned char -lha_calcsum(unsigned char sum, const void *pp, int offset, int size) +lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size) { unsigned char const *p = (unsigned char const *)pp; p += offset; - while (--size >= 0) + for (;size > 0; --size) sum += *p++; return (sum); } @@ -2014,18 +2017,18 @@ lzh_copy_from_window(struct lzh_stream *strm, struct lzh_dec *ds) if (ds->w_pos - ds->copy_pos <= strm->avail_out) copy_bytes = ds->w_pos - ds->copy_pos; else - copy_bytes = strm->avail_out; + copy_bytes = (size_t)strm->avail_out; memcpy(strm->next_out, ds->w_buff + ds->copy_pos, copy_bytes); - ds->copy_pos += copy_bytes; + ds->copy_pos += (int)copy_bytes; } else { if (ds->w_remaining <= strm->avail_out) copy_bytes = ds->w_remaining; else - copy_bytes = strm->avail_out; + copy_bytes = (size_t)strm->avail_out; memcpy(strm->next_out, ds->w_buff + ds->w_size - ds->w_remaining, copy_bytes); - ds->w_remaining -= copy_bytes; + ds->w_remaining -= (int)copy_bytes; } strm->next_out += copy_bytes; strm->avail_out -= copy_bytes; @@ -2479,7 +2482,7 @@ lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) bits = tbl_bits; else bits = HTBL_BITS; - hf->tbl = malloc((1 << bits) * sizeof(hf->tbl[0])); + hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0])); if (hf->tbl == NULL) return (ARCHIVE_FATAL); } @@ -2489,7 +2492,7 @@ lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) if (hf->tree == NULL) return (ARCHIVE_FATAL); } - hf->len_size = len_size; + hf->len_size = (int)len_size; hf->tbl_bits = tbl_bits; return (ARCHIVE_OK); } diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c index 6ac7db807..c4e7021a8 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2008 Joerg Sonnenberger - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,6 +55,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011 #ifndef O_BINARY #define O_BINARY 0 #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif #define MTREE_HAS_DEVICE 0x0001 #define MTREE_HAS_FFLAGS 0x0002 @@ -69,6 +72,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011 #define MTREE_HAS_UNAME 0x0400 #define MTREE_HAS_OPTIONAL 0x0800 +#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */ struct mtree_option { struct mtree_option *next; @@ -101,7 +105,9 @@ struct mtree { int64_t cur_size; }; +static int bid_keycmp(const char *, const char *, ssize_t); static int cleanup(struct archive_read *); +static int detect_form(struct archive_read *, int *); static int mtree_bid(struct archive_read *, int); static int parse_file(struct archive_read *, struct archive_entry *, struct mtree *, struct mtree_entry *, int *); @@ -199,7 +205,7 @@ archive_read_support_format_mtree(struct archive *_a) mtree->fd = -1; r = __archive_read_register_format(a, mtree, "mtree", - mtree_bid, NULL, read_header, read_data, skip, cleanup); + mtree_bid, NULL, read_header, read_data, skip, NULL, cleanup); if (r != ARCHIVE_OK) free(mtree); @@ -317,7 +323,7 @@ next_line(struct archive_read *a, * Returns the length of a mtree keyword if matched. * Returns 0 if not matched. */ -int +static int bid_keycmp(const char *p, const char *key, ssize_t len) { int match_len = 0; @@ -348,7 +354,7 @@ bid_keycmp(const char *p, const char *key, ssize_t len) * Returns the length of a detected keyword. * Returns 0 if any keywords were not found. */ -static ssize_t +static int bid_keyword(const char *p, ssize_t len) { static const char *keys_c[] = { @@ -367,7 +373,7 @@ bid_keyword(const char *p, ssize_t len) "md5", "md5digest", "mode", NULL }; static const char *keys_no[] = { - "nlink", "optional", NULL + "nlink", "nochange", "optional", NULL }; static const char *keys_r[] = { "rmd160", "rmd160digest", NULL @@ -407,7 +413,7 @@ bid_keyword(const char *p, ssize_t len) if (l > 0) return (l); } - return (0);/* Unkown key */ + return (0);/* Unknown key */ } /* @@ -418,7 +424,7 @@ bid_keyword(const char *p, ssize_t len) * When "unset" is specified, expects a set of "<space characters>keyword". */ static int -bid_keyword_list(const char *p, ssize_t len, int unset) +bid_keyword_list(const char *p, ssize_t len, int unset, int last_is_path) { int l; int keycnt = 0; @@ -436,8 +442,10 @@ bid_keyword_list(const char *p, ssize_t len, int unset) break; if (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r')) break; - if (!blank) /* No blank character. */ + if (!blank && !last_is_path) /* No blank character. */ return (-1); + if (last_is_path && len == 0) + return (keycnt); if (unset) { l = bid_keycmp(p, "all", len); @@ -472,7 +480,7 @@ bid_keyword_list(const char *p, ssize_t len, int unset) } static int -bid_entry(const char *p, ssize_t len) +bid_entry(const char *p, ssize_t len, ssize_t nl, int *last_is_path) { int f = 0; static const unsigned char safe_char[256] = { @@ -499,22 +507,60 @@ bid_entry(const char *p, ssize_t len) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ }; + ssize_t ll = len; + const char *pp = p; + *last_is_path = 0; /* * Skip the path-name which is quoted. */ - while (len > 0 && *p != ' ' && *p != '\t') { - if (!safe_char[*(const unsigned char *)p]) - return (-1); - ++p; - --len; + while (ll > 0 && *pp != ' ' &&*pp != '\t' && *pp != '\r' && + *pp != '\n') { + if (!safe_char[*(const unsigned char *)pp]) { + f = 0; + break; + } + ++pp; + --ll; ++f; } - /* If a path-name was not found, returns error. */ - if (f == 0) - return (-1); + /* If a path-name was not found at the first, try to check + * a mtree format ``NetBSD's mtree -D'' creates, which + * places the path-name at the last. */ + if (f == 0) { + const char *pb = p + len - nl; + int name_len = 0; + int slash; + + /* Do not accept multi lines for form D. */ + if (pb-2 >= p && + pb[-1] == '\\' && (pb[-2] == ' ' || pb[-2] == '\t')) + return (-1); + if (pb-1 >= p && pb[-1] == '\\') + return (-1); + + slash = 0; + while (p <= --pb && *pb != ' ' && *pb != '\t') { + if (!safe_char[*(const unsigned char *)pb]) + return (-1); + name_len++; + /* The pathname should have a slash in this + * format. */ + if (*pb == '/') + slash = 1; + } + if (name_len == 0 || slash == 0) + return (-1); + /* If '/' is placed at the first in this field, this is not + * a valid filename. */ + if (pb[1] == '/') + return (-1); + ll = len - nl - name_len; + pp = p; + *last_is_path = 1; + } - return (bid_keyword_list(p, len, 0)); + return (bid_keyword_list(pp, ll, 0, *last_is_path)); } #define MAX_BID_ENTRY 3 @@ -524,14 +570,11 @@ mtree_bid(struct archive_read *a, int best_bid) { const char *signature = "#mtree"; const char *p; - ssize_t avail, ravail; - ssize_t len, nl; - int detected_bytes = 0, entry_cnt = 0, multiline = 0; (void)best_bid; /* UNUSED */ /* Now let's look at the actual header and see if it matches. */ - p = __archive_read_ahead(a, strlen(signature), &avail); + p = __archive_read_ahead(a, strlen(signature), NULL); if (p == NULL) return (-1); @@ -541,6 +584,24 @@ mtree_bid(struct archive_read *a, int best_bid) /* * There is not a mtree signature. Let's try to detect mtree format. */ + return (detect_form(a, NULL)); +} + +static int +detect_form(struct archive_read *a, int *is_form_d) +{ + const char *p; + ssize_t avail, ravail; + ssize_t detected_bytes = 0, len, nl; + int entry_cnt = 0, multiline = 0; + int form_D = 0;/* The archive is generated by `NetBSD mtree -D' + * (In this source we call it `form D') . */ + + if (is_form_d != NULL) + *is_form_d = 0; + p = __archive_read_ahead(a, 1, &avail); + if (p == NULL) + return (-1); ravail = avail; for (;;) { len = next_line(a, &p, &avail, &ravail, &nl); @@ -565,7 +626,7 @@ mtree_bid(struct archive_read *a, int best_bid) } else { /* A continuance line; the terminal * character of previous line was '\' character. */ - if (bid_keyword_list(p, len, 0) <= 0) + if (bid_keyword_list(p, len, 0, 0) <= 0) break; if (multiline == 1) detected_bytes += len; @@ -580,9 +641,25 @@ mtree_bid(struct archive_read *a, int best_bid) continue; } if (p[0] != '/') { - if (bid_entry(p, len) >= 0) { + int last_is_path, keywords; + + keywords = bid_entry(p, len, nl, &last_is_path); + if (keywords >= 0) { detected_bytes += len; - if (p[len-nl-1] == '\\') + if (form_D == 0) { + if (last_is_path) + form_D = 1; + else if (keywords > 0) + /* This line is not `form D'. */ + form_D = -1; + } else if (form_D == 1) { + if (!last_is_path && keywords > 0) + /* This this is not `form D' + * and We cannot accept mixed + * format. */ + break; + } + if (!last_is_path && p[len-nl-1] == '\\') /* This line continues. */ multiline = 1; else { @@ -595,13 +672,13 @@ mtree_bid(struct archive_read *a, int best_bid) } else break; } else if (strncmp(p, "/set", 4) == 0) { - if (bid_keyword_list(p+4, len-4, 0) <= 0) + if (bid_keyword_list(p+4, len-4, 0, 0) <= 0) break; /* This line continues. */ if (p[len-nl-1] == '\\') multiline = 2; } else if (strncmp(p, "/unset", 6) == 0) { - if (bid_keyword_list(p+6, len-6, 1) <= 0) + if (bid_keyword_list(p+6, len-6, 1, 0) <= 0) break; /* This line continues. */ if (p[len-nl-1] == '\\') @@ -613,8 +690,13 @@ mtree_bid(struct archive_read *a, int best_bid) p += len; avail -= len; } - if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0)) + if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0)) { + if (is_form_d != NULL) { + if (form_D == 1) + *is_form_d = 1; + } return (32); + } return (0); } @@ -738,12 +820,12 @@ process_global_unset(struct archive_read *a, static int process_add_entry(struct archive_read *a, struct mtree *mtree, - struct mtree_option **global, const char *line, - struct mtree_entry **last_entry) + struct mtree_option **global, const char *line, ssize_t line_len, + struct mtree_entry **last_entry, int is_form_d) { struct mtree_entry *entry; struct mtree_option *iter; - const char *next, *eq; + const char *next, *eq, *name, *end; size_t len; int r; @@ -764,17 +846,46 @@ process_add_entry(struct archive_read *a, struct mtree *mtree, (*last_entry)->next = entry; *last_entry = entry; - len = strcspn(line, " \t\r\n"); + if (is_form_d) { + /* + * This form places the file name as last parameter. + */ + name = line + line_len -1; + while (line_len > 0) { + if (*name != '\r' && *name != '\n' && + *name != '\t' && *name != ' ') + break; + name--; + line_len--; + } + len = 0; + while (line_len > 0) { + if (*name == '\r' || *name == '\n' || + *name == '\t' || *name == ' ') { + name++; + break; + } + name--; + line_len--; + len++; + } + end = name; + } else { + len = strcspn(line, " \t\r\n"); + name = line; + line += len; + end = line + line_len; + } + if ((entry->name = malloc(len + 1)) == NULL) { archive_set_error(&a->archive, errno, "Can't allocate memory"); return (ARCHIVE_FATAL); } - memcpy(entry->name, line, len); + memcpy(entry->name, name, len); entry->name[len] = '\0'; parse_escapes(entry->name, entry); - line += len; for (iter = *global; iter != NULL; iter = iter->next) { r = add_option(a, &entry->options, iter->value, strlen(iter->value)); @@ -786,6 +897,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree, next = line + strspn(line, " \t\r\n"); if (*next == '\0') return (ARCHIVE_OK); + if (next >= end) + return (ARCHIVE_OK); line = next; next = line + strcspn(line, " \t\r\n"); eq = strchr(line, '='); @@ -810,7 +923,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree) char *p; struct mtree_option *global; struct mtree_entry *last_entry; - int r; + int r, is_form_d; mtree->archive_format = ARCHIVE_FORMAT_MTREE; mtree->archive_format_name = "mtree"; @@ -818,6 +931,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree) global = NULL; last_entry = NULL; + (void)detect_form(a, &is_form_d); + for (counter = 1; ; ++counter) { len = readline(a, mtree, &p, 65536); if (len == 0) { @@ -827,7 +942,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree) } if (len < 0) { free_options(global); - return (len); + return ((int)len); } /* Leading whitespace is never significant, ignore it. */ while (*p == ' ' || *p == '\t') { @@ -840,8 +955,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree) if (*p == '\r' || *p == '\n' || *p == '\0') continue; if (*p != '/') { - r = process_add_entry(a, mtree, &global, p, - &last_entry); + r = process_add_entry(a, mtree, &global, p, len, + &last_entry, is_form_d); } else if (strncmp(p, "/set", 4) == 0) { if (p[4] != ' ' && p[4] != '\t') break; @@ -1007,7 +1122,8 @@ parse_file(struct archive_read *a, struct archive_entry *entry, if (archive_entry_filetype(entry) == AE_IFREG || archive_entry_filetype(entry) == AE_IFDIR) { - mtree->fd = open(path, O_RDONLY | O_BINARY); + mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(mtree->fd); if (mtree->fd == -1 && (errno != ENOENT || archive_strlen(&mtree->contents_name) > 0)) { @@ -1090,15 +1206,19 @@ parse_file(struct archive_read *a, struct archive_entry *entry, * if it wasn't already parsed from the specification. */ if (st != NULL) { - if ((parsed_kws & MTREE_HAS_DEVICE) == 0 && + if (((parsed_kws & MTREE_HAS_DEVICE) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) && (archive_entry_filetype(entry) == AE_IFCHR || archive_entry_filetype(entry) == AE_IFBLK)) archive_entry_set_rdev(entry, st->st_rdev); - if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0) + if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) archive_entry_set_gid(entry, st->st_gid); - if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0) + if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) archive_entry_set_uid(entry, st->st_uid); - if ((parsed_kws & MTREE_HAS_MTIME) == 0) { + if ((parsed_kws & MTREE_HAS_MTIME) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) { #if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC archive_entry_set_mtime(entry, st->st_mtime, st->st_mtimespec.tv_nsec); @@ -1118,11 +1238,14 @@ parse_file(struct archive_read *a, struct archive_entry *entry, archive_entry_set_mtime(entry, st->st_mtime, 0); #endif } - if ((parsed_kws & MTREE_HAS_NLINK) == 0) + if ((parsed_kws & MTREE_HAS_NLINK) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) archive_entry_set_nlink(entry, st->st_nlink); - if ((parsed_kws & MTREE_HAS_PERM) == 0) + if ((parsed_kws & MTREE_HAS_PERM) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) archive_entry_set_perm(entry, st->st_mode); - if ((parsed_kws & MTREE_HAS_SIZE) == 0) + if ((parsed_kws & MTREE_HAS_SIZE) == 0 || + (parsed_kws & MTREE_HAS_NOCHANGE) != 0) archive_entry_set_size(entry, st->st_size); archive_entry_set_ino(entry, st->st_ino); archive_entry_set_dev(entry, st->st_dev); @@ -1182,7 +1305,7 @@ parse_device(struct archive *a, struct archive_entry *entry, char *val) comma1 = strchr(val, ','); if (comma1 == NULL) { - archive_entry_set_dev(entry, mtree_atol10(&val)); + archive_entry_set_dev(entry, (dev_t)mtree_atol10(&val)); return (ARCHIVE_OK); } ++comma1; @@ -1193,8 +1316,8 @@ parse_device(struct archive *a, struct archive_entry *entry, char *val) return (ARCHIVE_WARN); } ++comma2; - archive_entry_set_rdevmajor(entry, mtree_atol(&comma1)); - archive_entry_set_rdevminor(entry, mtree_atol(&comma2)); + archive_entry_set_rdevmajor(entry, (dev_t)mtree_atol(&comma1)); + archive_entry_set_rdevminor(entry, (dev_t)mtree_atol(&comma2)); return (ARCHIVE_OK); } @@ -1212,6 +1335,10 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, if (*key == '\0') return (ARCHIVE_OK); + if (strcmp(key, "nochange") == 0) { + *parsed_kws |= MTREE_HAS_NOCHANGE; + return (ARCHIVE_OK); + } if (strcmp(key, "optional") == 0) { *parsed_kws |= MTREE_HAS_OPTIONAL; return (ARCHIVE_OK); @@ -1279,7 +1406,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, if (val[0] >= '0' && val[0] <= '9') { *parsed_kws |= MTREE_HAS_PERM; archive_entry_set_perm(entry, - mtree_atol8(&val)); + (mode_t)mtree_atol8(&val)); } else { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -1291,7 +1418,8 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, case 'n': if (strcmp(key, "nlink") == 0) { *parsed_kws |= MTREE_HAS_NLINK; - archive_entry_set_nlink(entry, mtree_atol10(&val)); + archive_entry_set_nlink(entry, + (unsigned int)mtree_atol10(&val)); break; } case 'r': @@ -1433,7 +1561,7 @@ read_data(struct archive_read *a, const void **buff, size_t *size, int64_t *offs *buff = mtree->buff; *offset = mtree->offset; if ((int64_t)mtree->buffsize > mtree->cur_size - mtree->offset) - bytes_to_read = mtree->cur_size - mtree->offset; + bytes_to_read = (size_t)(mtree->cur_size - mtree->offset); else bytes_to_read = mtree->buffsize; bytes_read = read(mtree->fd, mtree->buff, bytes_to_read); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c index d5a8d86ee..dc1563d9e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c @@ -136,7 +136,7 @@ #define MAX_SYMBOLS 20 /* - * Considering L1,L2 cache miss and a calling of write sytem-call, + * Considering L1,L2 cache miss and a calling of write system-call, * the best size of the output buffer(uncompressed buffer) is 128K. * If the structure of extracting process is changed, this value * might be researched again. @@ -199,6 +199,13 @@ struct lzss int64_t position; }; +struct data_block_offsets +{ + int64_t header_size; + int64_t start_offset; + int64_t end_offset; +}; + struct rar { /* Entries from main RAR header */ @@ -217,6 +224,7 @@ struct rar long mnsec; mode_t mode; char *filename; + char *filename_save; size_t filename_allocated; /* File header optional entries */ @@ -234,6 +242,7 @@ struct rar int64_t bytes_uncopied; int64_t offset; int64_t offset_outgoing; + int64_t offset_seek; char valid; unsigned int unp_offset; unsigned int unp_buffer_size; @@ -243,6 +252,10 @@ struct rar char entry_eof; unsigned long crc_calculated; int found_first_header; + char has_endarc_header; + struct data_block_offsets *dbo; + unsigned int cursor; + unsigned int nodes; /* LZSS members */ struct huffman_code maincode; @@ -301,11 +314,13 @@ static int archive_read_format_rar_read_header(struct archive_read *, static int archive_read_format_rar_read_data(struct archive_read *, const void **, size_t *, int64_t *); static int archive_read_format_rar_read_data_skip(struct archive_read *a); +static int64_t archive_read_format_rar_seek_data(struct archive_read *, int64_t, + int); static int archive_read_format_rar_cleanup(struct archive_read *); /* Support functions */ static int read_header(struct archive_read *, struct archive_entry *, char); -static time_t get_time(int time); +static time_t get_time(int); static int read_exttime(const char *, struct rar *, const char *); static int read_symlink_stored(struct archive_read *, struct archive_entry *, struct archive_string_conv *); @@ -328,6 +343,7 @@ static int make_table_recurse(struct archive_read *, struct huffman_code *, int, static int64_t expand(struct archive_read *, int64_t); static int copy_from_lzss_window(struct archive_read *, const void **, int64_t, int); +static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *); /* * Bit stream reader. @@ -449,11 +465,9 @@ rar_br_fillup(struct archive_read *a, struct rar_br *br) __archive_read_consume(a, rar->bytes_unconsumed); rar->bytes_unconsumed = 0; } - br->next_in = __archive_read_ahead(a, 1, &(br->avail_in)); + br->next_in = rar_read_ahead(a, 1, &(br->avail_in)); if (br->next_in == NULL) return (0); - if (br->avail_in > rar->bytes_remaining) - br->avail_in = rar->bytes_remaining; if (br->avail_in == 0) return (0); } @@ -473,15 +487,13 @@ rar_br_preparation(struct archive_read *a, struct rar_br *br) struct rar *rar = (struct rar *)(a->format->data); if (rar->bytes_remaining > 0) { - br->next_in = __archive_read_ahead(a, 1, &(br->avail_in)); + br->next_in = rar_read_ahead(a, 1, &(br->avail_in)); if (br->next_in == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated RAR file data"); return (ARCHIVE_FATAL); } - if (br->avail_in > rar->bytes_remaining) - br->avail_in = rar->bytes_remaining; if (br->cache_avail == 0) (void)rar_br_fillup(a, br); } @@ -522,7 +534,7 @@ lzss_size(struct lzss *lzss) static inline int lzss_offset_for_position(struct lzss *lzss, int64_t pos) { - return pos & lzss->mask; + return (int)(pos & lzss->mask); } static inline unsigned char * @@ -642,6 +654,7 @@ archive_read_support_format_rar(struct archive *_a) archive_read_format_rar_read_header, archive_read_format_rar_read_data, archive_read_format_rar_read_data_skip, + archive_read_format_rar_seek_data, archive_read_format_rar_cleanup); if (r != ARCHIVE_OK) @@ -757,11 +770,13 @@ archive_read_format_rar_options(struct archive_read *a, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "rar: unknown keyword ``%s''", key); - - return (ret); + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -842,13 +857,6 @@ archive_read_format_rar_read_header(struct archive_read *a, sizeof(rar->reserved2)); } - if (rar->main_flags & MHD_VOLUME || - rar->main_flags & MHD_FIRSTVOLUME) - { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "RAR volume support unavailable."); - return (ARCHIVE_FATAL); - } if (rar->main_flags & MHD_PASSWORD) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -856,7 +864,7 @@ archive_read_format_rar_read_header(struct archive_read *a, return (ARCHIVE_FATAL); } - crc32_val = crc32(0, (const unsigned char *)p + 2, skip - 2); + crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2); if ((crc32_val & 0xffff) != archive_le16dec(p)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Header CRC error"); @@ -873,6 +881,7 @@ archive_read_format_rar_read_header(struct archive_read *a, case SUB_HEAD: case PROTECT_HEAD: case SIGN_HEAD: + case ENDARC_HEAD: flags = archive_le16dec(p + 3); skip = archive_le16dec(p + 5); if (skip < 7) { @@ -898,13 +907,15 @@ archive_read_format_rar_read_header(struct archive_read *a, p = h; } - crc32_val = crc32(0, (const unsigned char *)p + 2, skip - 2); + crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2); if ((crc32_val & 0xffff) != archive_le16dec(p)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Header CRC error"); return (ARCHIVE_FATAL); } __archive_read_consume(a, skip); + if (head_type == ENDARC_HEAD) + return (ARCHIVE_EOF); break; case NEWSUB_HEAD: @@ -912,9 +923,6 @@ archive_read_format_rar_read_header(struct archive_read *a, return ret; break; - case ENDARC_HEAD: - return (ARCHIVE_EOF); - default: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file"); @@ -936,10 +944,12 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff, rar->bytes_unconsumed = 0; } - if (rar->entry_eof) { + if (rar->entry_eof || rar->offset_seek >= rar->unp_size) { *buff = NULL; *size = 0; *offset = rar->offset; + if (*offset < rar->unp_size) + *offset = rar->unp_size; return (ARCHIVE_EOF); } @@ -973,6 +983,7 @@ archive_read_format_rar_read_data_skip(struct archive_read *a) { struct rar *rar; int64_t bytes_skipped; + int ret; rar = (struct rar *)(a->format->data); @@ -987,9 +998,179 @@ archive_read_format_rar_read_data_skip(struct archive_read *a) if (bytes_skipped < 0) return (ARCHIVE_FATAL); } + + /* Compressed data to skip must be read from each header in a multivolume + * archive. + */ + if (rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER) + { + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret == (ARCHIVE_EOF)) + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret != (ARCHIVE_OK)) + return ret; + return archive_read_format_rar_read_data_skip(a); + } + return (ARCHIVE_OK); } +static int64_t +archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset, + int whence) +{ + int64_t client_offset, ret; + unsigned int i; + struct rar *rar = (struct rar *)(a->format->data); + + if (rar->compression_method == COMPRESS_METHOD_STORE) + { + /* Modify the offset for use with SEEK_SET */ + switch (whence) + { + case SEEK_CUR: + client_offset = rar->offset_seek; + break; + case SEEK_END: + client_offset = rar->unp_size; + break; + case SEEK_SET: + default: + client_offset = 0; + } + client_offset += offset; + if (client_offset < 0) + { + /* Can't seek past beginning of data block */ + return -1; + } + else if (client_offset > rar->unp_size) + { + /* + * Set the returned offset but only seek to the end of + * the data block. + */ + rar->offset_seek = client_offset; + client_offset = rar->unp_size; + } + + client_offset += rar->dbo[0].start_offset; + i = 0; + while (i < rar->cursor) + { + i++; + client_offset += rar->dbo[i].start_offset - rar->dbo[i-1].end_offset; + } + if (rar->main_flags & MHD_VOLUME) + { + /* Find the appropriate offset among the multivolume archive */ + while (1) + { + if (client_offset < rar->dbo[rar->cursor].start_offset && + rar->file_flags & FHD_SPLIT_BEFORE) + { + /* Search backwards for the correct data block */ + if (rar->cursor == 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Attempt to seek past beginning of RAR data block"); + return (ARCHIVE_FAILED); + } + rar->cursor--; + client_offset -= rar->dbo[rar->cursor+1].start_offset - + rar->dbo[rar->cursor].end_offset; + if (client_offset < rar->dbo[rar->cursor].start_offset) + continue; + ret = __archive_read_seek(a, rar->dbo[rar->cursor].start_offset - + rar->dbo[rar->cursor].header_size, SEEK_SET); + if (ret < (ARCHIVE_OK)) + return ret; + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret != (ARCHIVE_OK)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Error during seek of RAR file"); + return (ARCHIVE_FAILED); + } + rar->cursor--; + break; + } + else if (client_offset > rar->dbo[rar->cursor].end_offset && + rar->file_flags & FHD_SPLIT_AFTER) + { + /* Search forward for the correct data block */ + rar->cursor++; + if (rar->cursor < rar->nodes && + client_offset > rar->dbo[rar->cursor].end_offset) + { + client_offset += rar->dbo[rar->cursor].start_offset - + rar->dbo[rar->cursor-1].end_offset; + continue; + } + rar->cursor--; + ret = __archive_read_seek(a, rar->dbo[rar->cursor].end_offset, + SEEK_SET); + if (ret < (ARCHIVE_OK)) + return ret; + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret == (ARCHIVE_EOF)) + { + rar->has_endarc_header = 1; + ret = archive_read_format_rar_read_header(a, a->entry); + } + if (ret != (ARCHIVE_OK)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Error during seek of RAR file"); + return (ARCHIVE_FAILED); + } + client_offset += rar->dbo[rar->cursor].start_offset - + rar->dbo[rar->cursor-1].end_offset; + continue; + } + break; + } + } + + ret = __archive_read_seek(a, client_offset, SEEK_SET); + if (ret < (ARCHIVE_OK)) + return ret; + rar->bytes_remaining = rar->dbo[rar->cursor].end_offset - ret; + i = rar->cursor; + while (i > 0) + { + i--; + ret -= rar->dbo[i+1].start_offset - rar->dbo[i].end_offset; + } + ret -= rar->dbo[0].start_offset; + + /* Always restart reading the file after a seek */ + a->read_data_block = NULL; + a->read_data_offset = 0; + a->read_data_output_offset = 0; + a->read_data_remaining = 0; + rar->bytes_unconsumed = 0; + rar->offset = 0; + + /* + * If a seek past the end of file was requested, return the requested + * offset. + */ + if (ret == rar->unp_size && rar->offset_seek > rar->unp_size) + return rar->offset_seek; + + /* Return the new offset */ + rar->offset_seek = ret; + return rar->offset_seek; + } + else + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Seeking of compressed RAR files is unsupported"); + } + return (ARCHIVE_FAILED); +} + static int archive_read_format_rar_cleanup(struct archive_read *a) { @@ -998,6 +1179,8 @@ archive_read_format_rar_cleanup(struct archive_read *a) rar = (struct rar *)(a->format->data); free_codes(a); free(rar->filename); + free(rar->filename_save); + free(rar->dbo); free(rar->unp_buffer); free(rar->lzss.window); __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc); @@ -1021,7 +1204,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, char *strp; char packed_size[8]; char unp_size[8]; - int time; + int ttime; struct archive_string_conv *sconv, *fn_sconv; unsigned long crc32_val; int ret = (ARCHIVE_OK), ret2; @@ -1047,7 +1230,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, memcpy(&rar_header, p, sizeof(rar_header)); rar->file_flags = archive_le16dec(rar_header.flags); header_size = archive_le16dec(rar_header.size); - if (header_size < sizeof(file_header) + 7) { + if (header_size < (int64_t)sizeof(file_header) + 7) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid header size"); return (ARCHIVE_FATAL); @@ -1082,11 +1265,11 @@ read_header(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_FATAL); } - if ((h = __archive_read_ahead(a, header_size - 7, NULL)) == NULL) + if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) return (ARCHIVE_FATAL); /* File Header CRC check. */ - crc32_val = crc32(crc32_val, h, header_size - 7); + crc32_val = crc32(crc32_val, h, (unsigned)(header_size - 7)); if ((crc32_val & 0xffff) != archive_le16dec(rar_header.crc)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Header CRC error"); @@ -1100,8 +1283,8 @@ read_header(struct archive_read *a, struct archive_entry *entry, rar->compression_method = file_header.method; - time = archive_le32dec(file_header.file_time); - rar->mtime = get_time(time); + ttime = archive_le32dec(file_header.file_time); + rar->mtime = get_time(ttime); rar->file_crc = archive_le32dec(file_header.file_crc); @@ -1129,9 +1312,6 @@ read_header(struct archive_read *a, struct archive_entry *entry, rar->unp_size = archive_le32dec(file_header.unp_size); } - /* TODO: Need to use CRC check for these kind of cases. - * For now, check if sizes are not < 0. - */ if (rar->packed_size < 0 || rar->unp_size < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -1139,6 +1319,8 @@ read_header(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_FATAL); } + rar->bytes_remaining = rar->packed_size; + /* TODO: RARv3 subblocks contain comments. For now the complete block is * consumed at the end. */ @@ -1146,7 +1328,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, size_t distance = p - (const char *)h; header_size += rar->packed_size; /* Make sure we have the extended data. */ - if ((h = __archive_read_ahead(a, header_size - 7, NULL)) == NULL) + if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) return (ARCHIVE_FATAL); p = h; endp = p + header_size - 7; @@ -1159,13 +1341,17 @@ read_header(struct archive_read *a, struct archive_entry *entry, "Invalid filename size"); return (ARCHIVE_FATAL); } - if (rar->filename_allocated < filename_size+2) { - rar->filename = realloc(rar->filename, filename_size+2); - if (rar->filename == NULL) { + if (rar->filename_allocated < filename_size * 2 + 2) { + char *newptr; + size_t newsize = filename_size * 2 + 2; + newptr = realloc(rar->filename, newsize); + if (newptr == NULL) { archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); return (ARCHIVE_FATAL); } + rar->filename = newptr; + rar->filename_allocated = newsize; } filename = rar->filename; memcpy(filename, p, filename_size); @@ -1174,15 +1360,17 @@ read_header(struct archive_read *a, struct archive_entry *entry, { if (filename_size != strlen(filename)) { - unsigned char highbyte, flagbits, flagbyte, length, offset; + unsigned char highbyte, flagbits, flagbyte; + unsigned fn_end, offset; end = filename_size; + fn_end = filename_size * 2; filename_size = 0; - offset = strlen(filename) + 1; + offset = (unsigned)strlen(filename) + 1; highbyte = *(p + offset++); flagbits = 0; flagbyte = 0; - while (offset < end && filename_size < end) + while (offset < end && filename_size < fn_end) { if (!flagbits) { @@ -1208,19 +1396,26 @@ read_header(struct archive_read *a, struct archive_entry *entry, break; case 3: { - length = *(p + offset++); - while (length) - { - if (filename_size >= end) - break; - filename[filename_size++] = *(p + offset); + char extra, high; + uint8_t length = *(p + offset++); + + if (length & 0x80) { + extra = *(p + offset++); + high = (char)highbyte; + } else + extra = high = 0; + length = (length & 0x7f) + 2; + while (length && filename_size < fn_end) { + unsigned cp = filename_size >> 1; + filename[filename_size++] = high; + filename[filename_size++] = p[cp] + extra; length--; } } break; } } - if (filename_size >= end) { + if (filename_size > fn_end) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid filename"); return (ARCHIVE_FATAL); @@ -1272,6 +1467,51 @@ read_header(struct archive_read *a, struct archive_entry *entry, p += filename_size; } + /* Split file in multivolume RAR. No more need to process header. */ + if (rar->filename_save && + !memcmp(rar->filename, rar->filename_save, filename_size + 1)) + { + __archive_read_consume(a, header_size - 7); + rar->cursor++; + if (rar->cursor >= rar->nodes) + { + rar->nodes++; + if ((rar->dbo = + realloc(rar->dbo, sizeof(*rar->dbo) * rar->nodes)) == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); + return (ARCHIVE_FATAL); + } + rar->dbo[rar->cursor].header_size = header_size; + rar->dbo[rar->cursor].start_offset = -1; + rar->dbo[rar->cursor].end_offset = -1; + } + if (rar->dbo[rar->cursor].start_offset < 0) + { + rar->dbo[rar->cursor].start_offset = a->filter->position; + rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset + + rar->packed_size; + } + return ret; + } + + rar->filename_save = (char*)realloc(rar->filename_save, + filename_size + 1); + memcpy(rar->filename_save, rar->filename, filename_size + 1); + + /* Set info for seeking */ + free(rar->dbo); + if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); + return (ARCHIVE_FATAL); + } + rar->dbo[0].header_size = header_size; + rar->dbo[0].start_offset = -1; + rar->dbo[0].end_offset = -1; + rar->cursor = 0; + rar->nodes = 1; + if (rar->file_flags & FHD_SALT) { if (p + 8 > endp) { @@ -1292,6 +1532,8 @@ read_header(struct archive_read *a, struct archive_entry *entry, } __archive_read_consume(a, header_size - 7); + rar->dbo[0].start_offset = a->filter->position; + rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size; switch(file_header.host_os) { @@ -1318,9 +1560,10 @@ read_header(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_FATAL); } - rar->bytes_remaining = rar->packed_size; rar->bytes_uncopied = rar->bytes_unconsumed = 0; - rar->lzss.position = rar->dictionary_size = rar->offset = 0; + rar->lzss.position = rar->offset = 0; + rar->offset_seek = 0; + rar->dictionary_size = 0; rar->offset_outgoing = 0; rar->br.cache_avail = 0; rar->br.avail_in = 0; @@ -1381,15 +1624,15 @@ read_header(struct archive_read *a, struct archive_entry *entry, } static time_t -get_time(int time) +get_time(int ttime) { struct tm tm; - tm.tm_sec = 2 * (time & 0x1f); - tm.tm_min = (time >> 5) & 0x3f; - tm.tm_hour = (time >> 11) & 0x1f; - tm.tm_mday = (time >> 16) & 0x1f; - tm.tm_mon = ((time >> 21) & 0x0f) - 1; - tm.tm_year = ((time >> 25) & 0x7f) + 80; + tm.tm_sec = 2 * (ttime & 0x1f); + tm.tm_min = (ttime >> 5) & 0x3f; + tm.tm_hour = (ttime >> 11) & 0x1f; + tm.tm_mday = (ttime >> 16) & 0x1f; + tm.tm_mon = ((ttime >> 21) & 0x0f) - 1; + tm.tm_year = ((ttime >> 25) & 0x7f) + 80; tm.tm_isdst = -1; return mktime(&tm); } @@ -1398,7 +1641,7 @@ static int read_exttime(const char *p, struct rar *rar, const char *endp) { unsigned rmode, flags, rem, j, count; - int time, i; + int ttime, i; struct tm *tm; time_t t; long nsec; @@ -1420,8 +1663,8 @@ read_exttime(const char *p, struct rar *rar, const char *endp) { if (p + 4 > endp) return (-1); - time = archive_le32dec(p); - t = get_time(time); + ttime = archive_le32dec(p); + t = get_time(ttime); p += 4; } rem = 0; @@ -1475,11 +1718,12 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry, int ret = (ARCHIVE_OK); rar = (struct rar *)(a->format->data); - if ((h = __archive_read_ahead(a, rar->packed_size, NULL)) == NULL) + if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL) return (ARCHIVE_FATAL); p = h; - if (archive_entry_copy_symlink_l(entry, p, rar->packed_size, sconv)) + if (archive_entry_copy_symlink_l(entry, + p, (size_t)rar->packed_size, sconv)) { if (errno == ENOMEM) { @@ -1504,7 +1748,8 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size, ssize_t bytes_avail; rar = (struct rar *)(a->format->data); - if (rar->bytes_remaining == 0) + if (rar->bytes_remaining == 0 && + !(rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER)) { *buff = NULL; *size = 0; @@ -1518,23 +1763,23 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size, return (ARCHIVE_EOF); } - *buff = __archive_read_ahead(a, 1, &bytes_avail); + *buff = rar_read_ahead(a, 1, &bytes_avail); if (bytes_avail <= 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated RAR file data"); return (ARCHIVE_FATAL); } - if (bytes_avail > rar->bytes_remaining) - bytes_avail = rar->bytes_remaining; *size = bytes_avail; *offset = rar->offset; rar->offset += bytes_avail; + rar->offset_seek += bytes_avail; rar->bytes_remaining -= bytes_avail; rar->bytes_unconsumed = bytes_avail; /* Calculate File CRC. */ - rar->crc_calculated = crc32(rar->crc_calculated, *buff, bytes_avail); + rar->crc_calculated = crc32(rar->crc_calculated, *buff, + (unsigned)bytes_avail); return (ARCHIVE_OK); } @@ -1564,7 +1809,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, *offset = rar->offset_outgoing; rar->offset_outgoing += *size; /* Calculate File CRC. */ - rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size); + rar->crc_calculated = crc32(rar->crc_calculated, *buff, + (unsigned)*size); rar->unp_offset = 0; return (ARCHIVE_OK); } @@ -1585,8 +1831,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset)) bs = rar->unp_buffer_size - rar->unp_offset; else - bs = rar->bytes_uncopied; - ret = copy_from_lzss_window(a, buff, rar->offset, bs); + bs = (size_t)rar->bytes_uncopied; + ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs); if (ret != ARCHIVE_OK) return (ret); rar->offset += bs; @@ -1597,7 +1843,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, *offset = rar->offset_outgoing; rar->offset_outgoing += *size; /* Calculate File CRC. */ - rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size); + rar->crc_calculated = crc32(rar->crc_calculated, *buff, + (unsigned)*size); return (ret); } continue; @@ -1713,8 +1960,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset)) bs = rar->unp_buffer_size - rar->unp_offset; else - bs = rar->bytes_uncopied; - ret = copy_from_lzss_window(a, buff, rar->offset, bs); + bs = (size_t)rar->bytes_uncopied; + ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs); if (ret != ARCHIVE_OK) return (ret); rar->offset += bs; @@ -1730,7 +1977,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, *offset = rar->offset_outgoing; rar->offset_outgoing += *size; /* Calculate File CRC. */ - rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size); + rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size); return ret; } @@ -1973,17 +2220,21 @@ parse_codes(struct archive_read *a) /* Seems as though dictionary sizes are not used. Even so, minimize * memory usage as much as possible. */ + void *new_window; + unsigned int new_size; + if (rar->unp_size >= DICTIONARY_MAX_SIZE) - rar->dictionary_size = DICTIONARY_MAX_SIZE; + new_size = DICTIONARY_MAX_SIZE; else - rar->dictionary_size = rar_fls(rar->unp_size) << 1; - rar->lzss.window = (unsigned char *)realloc(rar->lzss.window, - rar->dictionary_size); - if (rar->lzss.window == NULL) { + new_size = rar_fls((unsigned int)rar->unp_size) << 1; + new_window = realloc(rar->lzss.window, new_size); + if (new_window == NULL) { archive_set_error(&a->archive, ENOMEM, "Unable to allocate memory for uncompressed data."); return (ARCHIVE_FATAL); } + rar->lzss.window = (unsigned char *)new_window; + rar->dictionary_size = new_size; memset(rar->lzss.window, 0, rar->dictionary_size); rar->lzss.mask = rar->dictionary_size - 1; } @@ -2221,10 +2472,12 @@ add_value(struct archive_read *a, struct huffman_code *code, int value, static int new_node(struct huffman_code *code) { - code->tree = (struct huffman_tree_node *)realloc(code->tree, - (code->numentries + 1) * sizeof(*code->tree)); - if (code->tree == NULL) + void *new_tree; + + new_tree = realloc(code->tree, (code->numentries + 1) * sizeof(*code->tree)); + if (new_tree == NULL) return (-1); + code->tree = (struct huffman_tree_node *)new_tree; code->tree[code->numentries].branches[0] = -1; code->tree[code->numentries].branches[1] = -2; return 1; @@ -2239,8 +2492,8 @@ make_table(struct archive_read *a, struct huffman_code *code) code->tablesize = code->maxlength; code->table = - (struct huffman_table_entry *)malloc(sizeof(*code->table) - * (1 << code->tablesize)); + (struct huffman_table_entry *)calloc(1, sizeof(*code->table) + * ((size_t)1 << code->tablesize)); return make_table_recurse(a, code, 0, code->table, 0, code->tablesize); } @@ -2408,9 +2661,9 @@ expand(struct archive_read *a, int64_t end) if ((lensymbol = read_next_symbol(a, &rar->lengthcode)) < 0) goto bad_data; - if (lensymbol > sizeof(lengthbases)/sizeof(lengthbases[0])) + if (lensymbol > (int)(sizeof(lengthbases)/sizeof(lengthbases[0]))) goto bad_data; - if (lensymbol > sizeof(lengthbits)/sizeof(lengthbits[0])) + if (lensymbol > (int)(sizeof(lengthbits)/sizeof(lengthbits[0]))) goto bad_data; len = lengthbases[lensymbol] + 2; if (lengthbits[lensymbol] > 0) { @@ -2442,9 +2695,9 @@ expand(struct archive_read *a, int64_t end) } else { - if (symbol-271 > sizeof(lengthbases)/sizeof(lengthbases[0])) + if (symbol-271 > (int)(sizeof(lengthbases)/sizeof(lengthbases[0]))) goto bad_data; - if (symbol-271 > sizeof(lengthbits)/sizeof(lengthbits[0])) + if (symbol-271 > (int)(sizeof(lengthbits)/sizeof(lengthbits[0]))) goto bad_data; len = lengthbases[symbol-271]+3; if(lengthbits[symbol-271] > 0) { @@ -2456,9 +2709,9 @@ expand(struct archive_read *a, int64_t end) if ((offssymbol = read_next_symbol(a, &rar->offsetcode)) < 0) goto bad_data; - if (offssymbol > sizeof(offsetbases)/sizeof(offsetbases[0])) + if (offssymbol > (int)(sizeof(offsetbases)/sizeof(offsetbases[0]))) goto bad_data; - if (offssymbol > sizeof(offsetbits)/sizeof(offsetbits[0])) + if (offssymbol > (int)(sizeof(offsetbits)/sizeof(offsetbits[0]))) goto bad_data; offs = offsetbases[offssymbol]+1; if(offsetbits[offssymbol] > 0) @@ -2572,3 +2825,34 @@ copy_from_lzss_window(struct archive_read *a, const void **buffer, *buffer = NULL; return (ARCHIVE_OK); } + +static const void * +rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail) +{ + struct rar *rar = (struct rar *)(a->format->data); + const void *h = __archive_read_ahead(a, min, avail); + int ret; + if (avail) + { + if (a->read_data_is_posix_read && *avail > (ssize_t)a->read_data_requested) + *avail = a->read_data_requested; + if (*avail > rar->bytes_remaining) + *avail = (ssize_t)rar->bytes_remaining; + if (*avail < 0) + return NULL; + else if (*avail == 0 && rar->main_flags & MHD_VOLUME && + rar->file_flags & FHD_SPLIT_AFTER) + { + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret == (ARCHIVE_EOF)) + { + rar->has_endarc_header = 1; + ret = archive_read_format_rar_read_header(a, a->entry); + } + if (ret != (ARCHIVE_OK)) + return NULL; + return rar_read_ahead(a, min, avail); + } + } + return h; +} diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_raw.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_raw.c index df2c00c96..843497878 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_raw.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_raw.c @@ -77,6 +77,7 @@ archive_read_support_format_raw(struct archive *_a) archive_read_format_raw_read_header, archive_read_format_raw_read_data, archive_read_format_raw_read_data_skip, + NULL, archive_read_format_raw_cleanup); if (r != ARCHIVE_OK) free(info); @@ -157,7 +158,7 @@ archive_read_format_raw_read_data(struct archive_read *a, /* Record and return an error. */ *size = 0; *offset = info->offset; - return (avail); + return ((int)avail); } } diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c index 89a1d4f2a..e9523cb68 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -210,10 +210,10 @@ static int read_body_to_string(struct archive_read *, struct tar *, struct archive_string *, const void *h, size_t *); static int solaris_sparse_parse(struct archive_read *, struct tar *, struct archive_entry *, const char *); -static int64_t tar_atol(const char *, unsigned); -static int64_t tar_atol10(const char *, unsigned); -static int64_t tar_atol256(const char *, unsigned); -static int64_t tar_atol8(const char *, unsigned); +static int64_t tar_atol(const char *, size_t); +static int64_t tar_atol10(const char *, size_t); +static int64_t tar_atol256(const char *, size_t); +static int64_t tar_atol8(const char *, size_t); static int tar_read_header(struct archive_read *, struct tar *, struct archive_entry *, size_t *); static int tohex(int c); @@ -253,6 +253,7 @@ archive_read_support_format_tar(struct archive *_a) archive_read_format_tar_read_header, archive_read_format_tar_read_data, archive_read_format_tar_skip, + NULL, archive_read_format_tar_cleanup); if (r != ARCHIVE_OK) @@ -369,7 +370,7 @@ archive_read_format_tar_options(struct archive_read *a, /* Handle UTF-8 filnames as libarchive 2.x */ tar->compat_2x = (val != NULL)?1:0; tar->init_default_conversion = tar->compat_2x; - ret = ARCHIVE_OK; + return (ARCHIVE_OK); } else if (strcmp(key, "hdrcharset") == 0) { if (val == NULL || val[0] == 0) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -383,11 +384,13 @@ archive_read_format_tar_options(struct archive_read *a, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "tar: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } /* utility function- this exists to centralize the logic of tracking @@ -525,56 +528,57 @@ archive_read_format_tar_read_data(struct archive_read *a, tar = (struct tar *)(a->format->data); -skip_hole: - /* Remove exhausted entries from sparse list. */ - while (tar->sparse_list != NULL && - tar->sparse_list->remaining == 0) { - p = tar->sparse_list; - tar->sparse_list = p->next; - free(p); - } + for (;;) { + /* Remove exhausted entries from sparse list. */ + while (tar->sparse_list != NULL && + tar->sparse_list->remaining == 0) { + p = tar->sparse_list; + tar->sparse_list = p->next; + free(p); + } - if (tar->entry_bytes_unconsumed) { - __archive_read_consume(a, tar->entry_bytes_unconsumed); - tar->entry_bytes_unconsumed = 0; - } + if (tar->entry_bytes_unconsumed) { + __archive_read_consume(a, tar->entry_bytes_unconsumed); + tar->entry_bytes_unconsumed = 0; + } - /* If we're at end of file, return EOF. */ - if (tar->sparse_list == NULL || tar->entry_bytes_remaining == 0) { - if (__archive_read_consume(a, tar->entry_padding) < 0) - return (ARCHIVE_FATAL); - tar->entry_padding = 0; - *buff = NULL; - *size = 0; - *offset = tar->realsize; - return (ARCHIVE_EOF); - } + /* If we're at end of file, return EOF. */ + if (tar->sparse_list == NULL || + tar->entry_bytes_remaining == 0) { + if (__archive_read_consume(a, tar->entry_padding) < 0) + return (ARCHIVE_FATAL); + tar->entry_padding = 0; + *buff = NULL; + *size = 0; + *offset = tar->realsize; + return (ARCHIVE_EOF); + } - *buff = __archive_read_ahead(a, 1, &bytes_read); - if (bytes_read < 0) - return (ARCHIVE_FATAL); - if (*buff == NULL) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Truncated tar archive"); - return (ARCHIVE_FATAL); + *buff = __archive_read_ahead(a, 1, &bytes_read); + if (bytes_read < 0) + return (ARCHIVE_FATAL); + if (*buff == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated tar archive"); + return (ARCHIVE_FATAL); + } + if (bytes_read > tar->entry_bytes_remaining) + bytes_read = (ssize_t)tar->entry_bytes_remaining; + /* Don't read more than is available in the + * current sparse block. */ + if (tar->sparse_list->remaining < bytes_read) + bytes_read = (ssize_t)tar->sparse_list->remaining; + *size = bytes_read; + *offset = tar->sparse_list->offset; + tar->sparse_list->remaining -= bytes_read; + tar->sparse_list->offset += bytes_read; + tar->entry_bytes_remaining -= bytes_read; + tar->entry_bytes_unconsumed = bytes_read; + + if (!tar->sparse_list->hole) + return (ARCHIVE_OK); + /* Current is hole data and skip this. */ } - if (bytes_read > tar->entry_bytes_remaining) - bytes_read = tar->entry_bytes_remaining; - /* Don't read more than is available in the - * current sparse block. */ - if (tar->sparse_list->remaining < bytes_read) - bytes_read = tar->sparse_list->remaining; - *size = bytes_read; - *offset = tar->sparse_list->offset; - tar->sparse_list->remaining -= bytes_read; - tar->sparse_list->offset += bytes_read; - tar->entry_bytes_remaining -= bytes_read; - tar->entry_bytes_unconsumed = bytes_read; - - if (tar->sparse_list->hole) - goto skip_hole; - - return (ARCHIVE_OK); } static int @@ -613,13 +617,14 @@ tar_read_header(struct archive_read *a, struct tar *tar, int err; const char *h; const struct archive_entry_header_ustar *header; + const struct archive_entry_header_gnutar *gnuheader; tar_flush_unconsumed(a, unconsumed); /* Read 512-byte header record */ h = __archive_read_ahead(a, 512, &bytes); if (bytes < 0) - return (bytes); + return ((int)bytes); if (bytes == 0) { /* EOF at a block boundary. */ /* Some writers do omit the block of nulls. <sigh> */ return (ARCHIVE_EOF); @@ -700,7 +705,8 @@ tar_read_header(struct archive_read *a, struct tar *tar, err = header_pax_extensions(a, tar, entry, h, unconsumed); break; default: - if (memcmp(header->magic, "ustar \0", 8) == 0) { + gnuheader = (const struct archive_entry_header_gnutar *)h; + if (memcmp(gnuheader->magic, "ustar \0", 8) == 0) { a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR; a->archive.archive_format_name = "GNU tar format"; err = header_gnutar(a, tar, entry, h, unconsumed); @@ -749,7 +755,7 @@ tar_read_header(struct archive_read *a, struct tar *tar, bytes_read = gnu_sparse_10_read(a, tar, unconsumed); tar->entry_bytes_remaining -= bytes_read; if (bytes_read < 0) - return (bytes_read); + return ((int)bytes_read); } else { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -784,7 +790,7 @@ checksum(struct archive_read *a, const void *h) * Test the checksum. Note that POSIX specifies _unsigned_ * bytes for this calculation. */ - sum = tar_atol(header->checksum, sizeof(header->checksum)); + sum = (int)tar_atol(header->checksum, sizeof(header->checksum)); check = 0; for (i = 0; i < 148; i++) check += (unsigned char)bytes[i]; @@ -845,7 +851,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar, * more to make sure that we don't overrun acl_text later. */ header = (const struct archive_entry_header_ustar *)h; - size = tar_atol(header->size, sizeof(header->size)); + size = (size_t)tar_atol(header->size, sizeof(header->size)); err = read_body_to_string(a, tar, &(tar->acl_text), h, unconsumed); if (err != ARCHIVE_OK) return (err); @@ -1019,7 +1025,7 @@ read_body_to_string(struct archive_read *a, struct tar *tar, } /* Fail if we can't make our buffer big enough. */ - if (archive_string_ensure(as, size+1) == NULL) { + if (archive_string_ensure(as, (size_t)size+1) == NULL) { archive_set_error(&a->archive, ENOMEM, "No memory"); return (ARCHIVE_FATAL); @@ -1028,15 +1034,15 @@ read_body_to_string(struct archive_read *a, struct tar *tar, tar_flush_unconsumed(a, unconsumed); /* Read the body into the string. */ - *unconsumed = (size + 511) & ~ 511; + *unconsumed = (size_t)((size + 511) & ~ 511); src = __archive_read_ahead(a, *unconsumed, NULL); if (src == NULL) { *unconsumed = 0; return (ARCHIVE_FATAL); } - memcpy(as->s, src, size); + memcpy(as->s, src, (size_t)size); as->s[size] = '\0'; - as->length = size; + as->length = (size_t)size; return (ARCHIVE_OK); } @@ -1066,7 +1072,8 @@ header_common(struct archive_read *a, struct tar *tar, archive_string_empty(&(tar->entry_linkpath)); /* Parse out the numeric fields (all are octal) */ - archive_entry_set_mode(entry, tar_atol(header->mode, sizeof(header->mode))); + archive_entry_set_mode(entry, + (mode_t)tar_atol(header->mode, sizeof(header->mode))); archive_entry_set_uid(entry, tar_atol(header->uid, sizeof(header->uid))); archive_entry_set_gid(entry, tar_atol(header->gid, sizeof(header->gid))); tar->entry_bytes_remaining = tar_atol(header->size, sizeof(header->size)); @@ -1308,13 +1315,13 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar, * Q: Is the above idea really possible? Even * when there are GNU or pax extension entries? */ - data = __archive_read_ahead(a, size, NULL); + data = __archive_read_ahead(a, (size_t)size, NULL); if (data == NULL) { *unconsumed = 0; return (ARCHIVE_FATAL); } - archive_entry_copy_mac_metadata(entry, data, size); - *unconsumed = (size + 511) & ~ 511; + archive_entry_copy_mac_metadata(entry, data, (size_t)size); + *unconsumed = (size_t)((size + 511) & ~ 511); tar_flush_unconsumed(a, unconsumed); return (tar_read_header(a, tar, entry, unconsumed)); } @@ -1422,9 +1429,9 @@ header_ustar(struct archive_read *a, struct tar *tar, /* Parse out device numbers only for char and block specials. */ if (header->typeflag[0] == '3' || header->typeflag[0] == '4') { - archive_entry_set_rdevmajor(entry, + archive_entry_set_rdevmajor(entry, (dev_t) tar_atol(header->rdevmajor, sizeof(header->rdevmajor))); - archive_entry_set_rdevminor(entry, + archive_entry_set_rdevminor(entry, (dev_t) tar_atol(header->rdevminor, sizeof(header->rdevminor))); } @@ -1661,6 +1668,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, long n; int err = ARCHIVE_OK, r; + if (value == NULL) + value = ""; /* Disable compiler warning; do not pass + * NULL pointer to strlen(). */ switch (key[0]) { case 'G': /* GNU "0.0" sparse pax format. */ @@ -1707,11 +1717,11 @@ pax_attribute(struct archive_read *a, struct tar *tar, /* GNU "1.0" sparse pax format */ if (strcmp(key, "GNU.sparse.major") == 0) { - tar->sparse_gnu_major = tar_atol10(value, strlen(value)); + tar->sparse_gnu_major = (int)tar_atol10(value, strlen(value)); tar->sparse_gnu_pending = 1; } if (strcmp(key, "GNU.sparse.minor") == 0) { - tar->sparse_gnu_minor = tar_atol10(value, strlen(value)); + tar->sparse_gnu_minor = (int)tar_atol10(value, strlen(value)); tar->sparse_gnu_pending = 1; } if (strcmp(key, "GNU.sparse.name") == 0) { @@ -1794,20 +1804,20 @@ pax_attribute(struct archive_read *a, struct tar *tar, } } else if (strcmp(key, "SCHILY.devmajor") == 0) { archive_entry_set_rdevmajor(entry, - tar_atol10(value, strlen(value))); + (dev_t)tar_atol10(value, strlen(value))); } else if (strcmp(key, "SCHILY.devminor") == 0) { archive_entry_set_rdevminor(entry, - tar_atol10(value, strlen(value))); + (dev_t)tar_atol10(value, strlen(value))); } else if (strcmp(key, "SCHILY.fflags") == 0) { archive_entry_copy_fflags_text(entry, value); } else if (strcmp(key, "SCHILY.dev") == 0) { archive_entry_set_dev(entry, - tar_atol10(value, strlen(value))); + (dev_t)tar_atol10(value, strlen(value))); } else if (strcmp(key, "SCHILY.ino") == 0) { archive_entry_set_ino(entry, tar_atol10(value, strlen(value))); } else if (strcmp(key, "SCHILY.nlink") == 0) { - archive_entry_set_nlink(entry, + archive_entry_set_nlink(entry, (unsigned) tar_atol10(value, strlen(value))); } else if (strcmp(key, "SCHILY.realsize") == 0) { tar->realsize = tar_atol10(value, strlen(value)); @@ -2016,9 +2026,9 @@ header_gnutar(struct archive_read *a, struct tar *tar, /* Parse out device numbers only for char and block specials */ if (header->typeflag[0] == '3' || header->typeflag[0] == '4') { - archive_entry_set_rdevmajor(entry, + archive_entry_set_rdevmajor(entry, (dev_t) tar_atol(header->rdevmajor, sizeof(header->rdevmajor))); - archive_entry_set_rdevminor(entry, + archive_entry_set_rdevminor(entry, (dev_t) tar_atol(header->rdevminor, sizeof(header->rdevminor))); } else archive_entry_set_rdev(entry, 0); @@ -2253,7 +2263,8 @@ gnu_sparse_10_atol(struct archive_read *a, struct tar *tar, * don't require this, but they should. */ do { - bytes_read = readline(a, tar, &p, tar_min(*remaining, 100), unconsumed); + bytes_read = readline(a, tar, &p, + (ssize_t)tar_min(*remaining, 100), unconsumed); if (bytes_read <= 0) return (ARCHIVE_FATAL); *remaining -= bytes_read; @@ -2294,7 +2305,7 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed) remaining = tar->entry_bytes_remaining; /* Parse entries. */ - entries = gnu_sparse_10_atol(a, tar, &remaining, unconsumed); + entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed); if (entries < 0) return (ARCHIVE_FATAL); /* Parse the individual entries. */ @@ -2312,16 +2323,16 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed) } /* Skip rest of block... */ tar_flush_unconsumed(a, unconsumed); - bytes_read = tar->entry_bytes_remaining - remaining; + bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining); to_skip = 0x1ff & -bytes_read; if (to_skip != __archive_read_consume(a, to_skip)) return (ARCHIVE_FATAL); - return (bytes_read + to_skip); + return ((ssize_t)(bytes_read + to_skip)); } /* * Solaris pax extension for a sparse file. This is recorded with the - * data and hole pairs. The way recording sparse infomation by Solaris' + * data and hole pairs. The way recording sparse information by Solaris' * pax simply indicates where data and sparse are, so the stored contents * consist of both data and hole. */ @@ -2333,6 +2344,8 @@ solaris_sparse_parse(struct archive_read *a, struct tar *tar, int64_t start, end; int hole = 1; + (void)entry; /* UNUSED */ + end = 0; if (*p == ' ') p++; @@ -2380,7 +2393,7 @@ solaris_sparse_parse(struct archive_read *a, struct tar *tar, * On read, this implementation supports both extensions. */ static int64_t -tar_atol(const char *p, unsigned char_cnt) +tar_atol(const char *p, size_t char_cnt) { /* * Technically, GNU tar considers a field to be in base-256 @@ -2397,70 +2410,55 @@ tar_atol(const char *p, unsigned char_cnt) * it does obey locale. */ static int64_t -tar_atol8(const char *p, unsigned char_cnt) +tar_atol_base_n(const char *p, size_t char_cnt, int base) { int64_t l, limit, last_digit_limit; - int digit, sign, base; + int digit, sign; - base = 8; limit = INT64_MAX / base; last_digit_limit = INT64_MAX % base; - while (*p == ' ' || *p == '\t') + /* the pointer will not be dereferenced if char_cnt is zero + * due to the way the && operator is evaulated. + */ + while (char_cnt != 0 && (*p == ' ' || *p == '\t')) { p++; - if (*p == '-') { + char_cnt--; + } + + sign = 1; + if (char_cnt != 0 && *p == '-') { sign = -1; p++; - } else - sign = 1; + char_cnt--; + } l = 0; - digit = *p - '0'; - while (digit >= 0 && digit < base && char_cnt-- > 0) { - if (l>limit || (l == limit && digit > last_digit_limit)) { - l = INT64_MAX; /* Truncate on overflow. */ - break; + if (char_cnt != 0) { + digit = *p - '0'; + while (digit >= 0 && digit < base && char_cnt != 0) { + if (l>limit || (l == limit && digit > last_digit_limit)) { + l = INT64_MAX; /* Truncate on overflow. */ + break; + } + l = (l * base) + digit; + digit = *++p - '0'; + char_cnt--; } - l = (l * base) + digit; - digit = *++p - '0'; } return (sign < 0) ? -l : l; } -/* - * Note that this implementation does not (and should not!) obey - * locale settings; you cannot simply substitute strtol here, since - * it does obey locale. - */ static int64_t -tar_atol10(const char *p, unsigned char_cnt) +tar_atol8(const char *p, size_t char_cnt) { - int64_t l, limit, last_digit_limit; - int base, digit, sign; - - base = 10; - limit = INT64_MAX / base; - last_digit_limit = INT64_MAX % base; - - while (*p == ' ' || *p == '\t') - p++; - if (*p == '-') { - sign = -1; - p++; - } else - sign = 1; + return tar_atol_base_n(p, char_cnt, 8); +} - l = 0; - digit = *p - '0'; - while (digit >= 0 && digit < base && char_cnt-- > 0) { - if (l > limit || (l == limit && digit > last_digit_limit)) { - l = INT64_MAX; /* Truncate on overflow. */ - break; - } - l = (l * base) + digit; - digit = *++p - '0'; - } - return (sign < 0) ? -l : l; +static int64_t +tar_atol10(const char *p, size_t char_cnt) +{ + return tar_atol_base_n(p, char_cnt, 10); } /* @@ -2469,7 +2467,7 @@ tar_atol10(const char *p, unsigned char_cnt) * ignored. */ static int64_t -tar_atol256(const char *_p, unsigned char_cnt) +tar_atol256(const char *_p, size_t char_cnt) { int64_t l, upper_limit, lower_limit; const unsigned char *p = (const unsigned char *)_p; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c index 0834e6fc3..2530e34e1 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c @@ -183,9 +183,9 @@ struct xar_file { time_t mtime; time_t atime; struct archive_string uname; - uid_t uid; + int64_t uid; struct archive_string gname; - gid_t gid; + int64_t gid; mode_t mode; dev_t dev; dev_t devmajor; @@ -467,6 +467,7 @@ archive_read_support_format_xar(struct archive *_a) xar_read_header, xar_read_data, xar_read_data_skip, + NULL, xar_cleanup); if (r != ARCHIVE_OK) free(xar); @@ -602,7 +603,8 @@ read_toc(struct archive_read *a) r = move_reading_point(a, xar->toc_chksum_offset); if (r != ARCHIVE_OK) return (r); - b = __archive_read_ahead(a, xar->toc_chksum_size, &bytes); + b = __archive_read_ahead(a, + (size_t)xar->toc_chksum_size, &bytes); if (bytes < 0) return ((int)bytes); if ((uint64_t)bytes < xar->toc_chksum_size) { @@ -611,7 +613,8 @@ read_toc(struct archive_read *a) "Truncated archive file"); return (ARCHIVE_FATAL); } - r = checksum_final(a, b, xar->toc_chksum_size, NULL, 0); + r = checksum_final(a, b, + (size_t)xar->toc_chksum_size, NULL, 0); __archive_read_consume(a, xar->toc_chksum_size); xar->offset += xar->toc_chksum_size; if (r != ARCHIVE_OK) @@ -2065,7 +2068,7 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list) xar->file->hdnext = xar->hdlink_orgs; xar->hdlink_orgs = xar->file; } else { - xar->file->link = atol10(attr->value, + xar->file->link = (unsigned)atol10(attr->value, strlen(attr->value)); if (xar->file->link > 0) if (add_link(a, xar, xar->file) != ARCHIVE_OK) { @@ -2624,6 +2627,7 @@ strappend_base64(struct xar *xar, const unsigned char *b; size_t len; + (void)xar; /* UNUSED */ len = 0; out = buff; b = (const unsigned char *)s; @@ -2760,7 +2764,7 @@ xml_data(void *userData, const char *s, int len) xar->file->has |= HAS_MODE; xar->file->mode = (xar->file->mode & AE_IFMT) | - (atol8(s, len) & ~AE_IFMT); + ((mode_t)(atol8(s, len)) & ~AE_IFMT); break; case FILE_GROUP: xar->file->has |= HAS_GID; @@ -3075,12 +3079,15 @@ xml2_xmlattr_setup(struct archive_read *a, attr->name = strdup( (const char *)xmlTextReaderConstLocalName(reader)); if (attr->name == NULL) { + free(attr); archive_set_error(&a->archive, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); } attr->value = strdup( (const char *)xmlTextReaderConstValue(reader)); if (attr->value == NULL) { + free(attr->name); + free(attr); archive_set_error(&a->archive, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); } diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c index d15080263..2fdc08b6a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2004 Tim Kientzle - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,23 +38,26 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102 #endif #include "archive.h" +#include "archive_endian.h" #include "archive_entry.h" #include "archive_entry_locale.h" #include "archive_private.h" +#include "archive_rb.h" #include "archive_read_private.h" -#include "archive_endian.h" #ifndef HAVE_ZLIB_H #include "archive_crc32.h" #endif struct zip_entry { + struct archive_rb_node node; int64_t local_header_offset; int64_t compressed_size; int64_t uncompressed_size; int64_t gid; int64_t uid; struct archive_entry *entry; + struct archive_string rsrcname; time_t mtime; time_t atime; time_t ctime; @@ -67,15 +70,19 @@ struct zip_entry { struct zip { /* Structural information about the archive. */ + int64_t end_of_central_directory_offset; int64_t central_directory_offset; size_t central_directory_size; size_t central_directory_entries; char have_central_directory; + int64_t offset; /* List of entries (seekable Zip only) */ size_t entries_remaining; struct zip_entry *zip_entries; struct zip_entry *entry; + struct archive_rb_tree tree; + struct archive_rb_tree tree_rsrc; size_t unconsumed; @@ -116,29 +123,36 @@ struct zip { #define ZIP_STRONG_ENCRYPTED (1<<6) #define ZIP_UTF8_NAME (1<<11) -static int archive_read_format_zip_streamable_bid(struct archive_read *, int); -static int archive_read_format_zip_seekable_bid(struct archive_read *, int); +static int archive_read_format_zip_streamable_bid(struct archive_read *, + int); +static int archive_read_format_zip_seekable_bid(struct archive_read *, + int); static int archive_read_format_zip_options(struct archive_read *, const char *, const char *); static int archive_read_format_zip_cleanup(struct archive_read *); static int archive_read_format_zip_read_data(struct archive_read *, const void **, size_t *, int64_t *); static int archive_read_format_zip_read_data_skip(struct archive_read *a); -static int archive_read_format_zip_seekable_read_header(struct archive_read *, - struct archive_entry *); -static int archive_read_format_zip_streamable_read_header(struct archive_read *, - struct archive_entry *); +static int archive_read_format_zip_seekable_read_header( + struct archive_read *, struct archive_entry *); +static int archive_read_format_zip_streamable_read_header( + struct archive_read *, struct archive_entry *); +static ssize_t zip_get_local_file_header_size(struct archive_read *, size_t); #ifdef HAVE_ZLIB_H +static int zip_deflate_init(struct archive_read *, struct zip *); static int zip_read_data_deflate(struct archive_read *a, const void **buff, size_t *size, int64_t *offset); #endif static int zip_read_data_none(struct archive_read *a, const void **buff, size_t *size, int64_t *offset); static int zip_read_local_file_header(struct archive_read *a, - struct archive_entry *entry, struct zip *); + struct archive_entry *entry, struct zip *); static time_t zip_time(const char *); static const char *compression_name(int compression); -static void process_extra(const char *, size_t, struct zip_entry *); +static void process_extra(const char *, size_t, struct zip_entry *); + +int archive_read_support_format_zip_streamable(struct archive *); +int archive_read_support_format_zip_seekable(struct archive *); int archive_read_support_format_zip_streamable(struct archive *_a) @@ -166,6 +180,7 @@ archive_read_support_format_zip_streamable(struct archive *_a) archive_read_format_zip_streamable_read_header, archive_read_format_zip_read_data, archive_read_format_zip_read_data_skip, + NULL, archive_read_format_zip_cleanup); if (r != ARCHIVE_OK) @@ -199,6 +214,7 @@ archive_read_support_format_zip_seekable(struct archive *_a) archive_read_format_zip_seekable_read_header, archive_read_format_zip_read_data, archive_read_format_zip_read_data_skip, + NULL, archive_read_format_zip_cleanup); if (r != ARCHIVE_OK) @@ -217,14 +233,13 @@ archive_read_support_format_zip(struct archive *a) } /* - * TODO: This is a performance sink because it forces - * the read core to drop buffered data from the start - * of file, which will then have to be re-read again - * if this bidder loses. + * TODO: This is a performance sink because it forces the read core to + * drop buffered data from the start of file, which will then have to + * be re-read again if this bidder loses. * - * Consider passing in the winning bid value to subsequent - * bidders so that this bidder in particular can avoid - * seeking if it knows it's going to lose anyway. + * We workaround this a little by passing in the best bid so far so + * that later bidders can do nothing if they know they'll never + * outbid. But we can certainly do better... */ static int archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid) @@ -249,8 +264,48 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid) /* First four bytes are signature for end of central directory record. Four zero bytes ensure this isn't a multi-volume Zip file (which we don't yet support). */ - if (memcmp(p, "PK\005\006\000\000\000\000", 8) != 0) - return 0; + if (memcmp(p, "PK\005\006\000\000\000\000", 8) != 0) { + int64_t i, tail; + int found; + + /* + * If there is a comment in end of central directory + * record, 22 bytes are too short. we have to read more + * to properly detect the record. Hopefully, a length + * of the comment is not longer than 16362 bytes(16K-22). + */ + if (filesize + 22 > 1024 * 16) { + tail = 1024 * 16; + filesize = __archive_read_seek(a, tail * -1, SEEK_END); + } else { + tail = filesize + 22; + filesize = __archive_read_seek(a, 0, SEEK_SET); + } + if (filesize < 0) + return 0; + if ((p = __archive_read_ahead(a, (size_t)tail, NULL)) == NULL) + return 0; + for (found = 0, i = 0;!found && i < tail - 22;) { + switch (p[i]) { + case 'P': + if (memcmp(p+i, + "PK\005\006\000\000\000\000", 8) == 0) { + p += i; + filesize += tail - + (22 + archive_le16dec(p+20)); + found = 1; + } else + i += 8; + break; + case 'K': i += 7; break; + case 005: i += 6; break; + case 006: i += 5; break; + default: i += 1; break; + } + } + if (!found) + return 0; + } /* Since we've already done the hard work of finding the end of central directory record, let's save the important @@ -258,12 +313,14 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid) zip->central_directory_entries = archive_le16dec(p + 10); zip->central_directory_size = archive_le32dec(p + 12); zip->central_directory_offset = archive_le32dec(p + 16); + zip->end_of_central_directory_offset = filesize; /* Just one volume, so central dir must all be on this volume. */ if (zip->central_directory_entries != archive_le16dec(p + 8)) return 0; /* Central directory can't extend beyond end of this file. */ - if (zip->central_directory_offset + zip->central_directory_size > filesize) + if (zip->central_directory_offset + + (int64_t)zip->central_directory_size > filesize) return 0; /* This is just a tiny bit higher than the maximum returned by @@ -273,18 +330,117 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid) } static int +cmp_node(const struct archive_rb_node *n1, const struct archive_rb_node *n2) +{ + const struct zip_entry *e1 = (const struct zip_entry *)n1; + const struct zip_entry *e2 = (const struct zip_entry *)n2; + + return ((int)(e2->local_header_offset - e1->local_header_offset)); +} + +static int +cmp_key(const struct archive_rb_node *n, const void *key) +{ + /* This function won't be called */ + (void)n; /* UNUSED */ + (void)key; /* UNUSED */ + return 1; +} + +static int +rsrc_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct zip_entry *e1 = (const struct zip_entry *)n1; + const struct zip_entry *e2 = (const struct zip_entry *)n2; + + return (strcmp(e2->rsrcname.s, e1->rsrcname.s)); +} + +static int +rsrc_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct zip_entry *e = (const struct zip_entry *)n; + return (strcmp((const char *)key, e->rsrcname.s)); +} + +static const char * +rsrc_basename(const char *name, size_t name_length) +{ + const char *s, *r; + + r = s = name; + for (;;) { + s = memchr(s, '/', name_length - (s - name)); + if (s == NULL) + break; + r = ++s; + } + return (r); +} + +static void +expose_parent_dirs(struct zip *zip, const char *name, size_t name_length) +{ + struct archive_string str; + struct zip_entry *dir; + char *s; + + archive_string_init(&str); + archive_strncpy(&str, name, name_length); + for (;;) { + s = strrchr(str.s, '/'); + if (s == NULL) + break; + *s = '\0'; + /* Transfer the parent directory from zip->tree_rsrc RB + * tree to zip->tree RB tree to expose. */ + dir = (struct zip_entry *) + __archive_rb_tree_find_node(&zip->tree_rsrc, str.s); + if (dir == NULL) + break; + __archive_rb_tree_remove_node(&zip->tree_rsrc, &dir->node); + archive_string_free(&dir->rsrcname); + __archive_rb_tree_insert_node(&zip->tree, &dir->node); + } + archive_string_free(&str); +} + +static int slurp_central_directory(struct archive_read *a, struct zip *zip) { unsigned i; + int64_t correction; + static const struct archive_rb_tree_ops rb_ops = { + &cmp_node, &cmp_key + }; + static const struct archive_rb_tree_ops rb_rsrc_ops = { + &rsrc_cmp_node, &rsrc_cmp_key + }; + + /* + * Consider the archive file we are reading may be SFX. + * So we have to calculate a SFX header size to revise + * ZIP header offsets. + */ + correction = zip->end_of_central_directory_offset - + (zip->central_directory_offset + zip->central_directory_size); + /* The central directory offset is relative value, and so + * we revise this offset for SFX. */ + zip->central_directory_offset += correction; __archive_read_seek(a, zip->central_directory_offset, SEEK_SET); + zip->offset = zip->central_directory_offset; + __archive_rb_tree_init(&zip->tree, &rb_ops); + __archive_rb_tree_init(&zip->tree_rsrc, &rb_rsrc_ops); - zip->zip_entries = calloc(zip->central_directory_entries, sizeof(struct zip_entry)); + zip->zip_entries = calloc(zip->central_directory_entries, + sizeof(struct zip_entry)); for (i = 0; i < zip->central_directory_entries; ++i) { struct zip_entry *zip_entry = &zip->zip_entries[i]; size_t filename_length, extra_length, comment_length; uint32_t external_attributes; - const char *p; + const char *name, *p, *r; if ((p = __archive_read_ahead(a, 46, NULL)) == NULL) return ARCHIVE_FATAL; @@ -298,7 +454,7 @@ slurp_central_directory(struct archive_read *a, struct zip *zip) zip_entry->system = p[5]; /* version_required = archive_le16dec(p + 6); */ zip_entry->flags = archive_le16dec(p + 8); - zip_entry->compression = archive_le16dec(p + 10); + zip_entry->compression = (char)archive_le16dec(p + 10); zip_entry->mtime = zip_time(p + 12); zip_entry->crc32 = archive_le32dec(p + 16); zip_entry->compressed_size = archive_le32dec(p + 20); @@ -309,31 +465,233 @@ slurp_central_directory(struct archive_read *a, struct zip *zip) /* disk_start = archive_le16dec(p + 34); */ /* Better be zero. */ /* internal_attributes = archive_le16dec(p + 36); */ /* text bit */ external_attributes = archive_le32dec(p + 38); - zip_entry->local_header_offset = archive_le32dec(p + 42); + zip_entry->local_header_offset = + archive_le32dec(p + 42) + correction; + /* If we can't guess the mode, leave it zero here; + when we read the local file header we might get + more information. */ + zip_entry->mode = 0; if (zip_entry->system == 3) { zip_entry->mode = external_attributes >> 16; + } + + /* + * Mac resource fork files are stored under the + * "__MACOSX/" directory, so we should check if + * it is. + */ + /* Make sure we have the file name. */ + if ((p = __archive_read_ahead(a, 46 + filename_length, NULL)) + == NULL) + return ARCHIVE_FATAL; + name = p + 46; + r = rsrc_basename(name, filename_length); + if (filename_length >= 9 && + strncmp("__MACOSX/", name, 9) == 0) { + /* If this file is not a resource fork nor + * a directory. We should treat it as a non + * resource fork file to expose it. */ + if (name[filename_length-1] != '/' && + (r - name < 3 || r[0] != '.' || r[1] != '_')) { + __archive_rb_tree_insert_node(&zip->tree, + &zip_entry->node); + /* Expose its parent directories. */ + expose_parent_dirs(zip, name, filename_length); + } else { + /* This file is a resource fork file or + * a directory. */ + archive_strncpy(&(zip_entry->rsrcname), name, + filename_length); + __archive_rb_tree_insert_node(&zip->tree_rsrc, + &zip_entry->node); + } } else { - zip_entry->mode = AE_IFREG | 0777; + /* Generate resource fork name to find its resource + * file at zip->tree_rsrc. */ + archive_strcpy(&(zip_entry->rsrcname), "__MACOSX/"); + archive_strncat(&(zip_entry->rsrcname), name, r - name); + archive_strcat(&(zip_entry->rsrcname), "._"); + archive_strncat(&(zip_entry->rsrcname), + name + (r - name), filename_length - (r - name)); + /* Register an entry to RB tree to sort it by + * file offset. */ + __archive_rb_tree_insert_node(&zip->tree, + &zip_entry->node); } - /* Do we need to parse filename here? */ - /* Or can we wait until we read the local header? */ + /* We don't read the filename until we get to the + local file header. Reading it here would speed up + table-of-contents operations (removing the need to + find and read local file header to get the + filename) at the cost of requiring a lot of extra + space. */ + /* We don't read the extra block here. We assume it + will be duplicated at the local file header. */ __archive_read_consume(a, 46 + filename_length + extra_length + comment_length); } - /* TODO: Sort zip entries. */ - return ARCHIVE_OK; } +static int64_t +zip_read_consume(struct archive_read *a, int64_t bytes) +{ + struct zip *zip = (struct zip *)a->format->data; + int64_t skip; + + skip = __archive_read_consume(a, bytes); + if (skip > 0) + zip->offset += skip; + return (skip); +} + +static int +zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry, + struct zip_entry *rsrc) +{ + struct zip *zip = (struct zip *)a->format->data; + unsigned char *metadata, *mp; + int64_t offset = zip->offset; + size_t remaining_bytes, metadata_bytes; + ssize_t hsize; + int ret = ARCHIVE_OK, eof; + + switch(rsrc->compression) { + case 0: /* No compression. */ +#ifdef HAVE_ZLIB_H + case 8: /* Deflate compression. */ +#endif + break; + default: /* Unsupported compression. */ + /* Return a warning. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported ZIP compression method (%s)", + compression_name(rsrc->compression)); + /* We can't decompress this entry, but we will + * be able to skip() it and try the next entry. */ + return (ARCHIVE_WARN); + } + + if (rsrc->uncompressed_size > (128 * 1024)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Mac metadata is too large: %jd > 128K bytes", + (intmax_t)rsrc->uncompressed_size); + return (ARCHIVE_WARN); + } + + metadata = malloc((size_t)rsrc->uncompressed_size); + if (metadata == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Mac metadata"); + return (ARCHIVE_FATAL); + } + + if (zip->offset < rsrc->local_header_offset) + zip_read_consume(a, rsrc->local_header_offset - zip->offset); + else if (zip->offset != rsrc->local_header_offset) { + __archive_read_seek(a, rsrc->local_header_offset, SEEK_SET); + zip->offset = zip->entry->local_header_offset; + } + + hsize = zip_get_local_file_header_size(a, 0); + zip_read_consume(a, hsize); + + remaining_bytes = (size_t)rsrc->compressed_size; + metadata_bytes = (size_t)rsrc->uncompressed_size; + mp = metadata; + eof = 0; + while (!eof && remaining_bytes) { + const unsigned char *p; + ssize_t bytes_avail; + size_t bytes_used; + + p = __archive_read_ahead(a, 1, &bytes_avail); + if (p == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + ret = ARCHIVE_WARN; + goto exit_mac_metadata; + } + if ((size_t)bytes_avail > remaining_bytes) + bytes_avail = remaining_bytes; + switch(rsrc->compression) { + case 0: /* No compression. */ + memcpy(mp, p, bytes_avail); + bytes_used = (size_t)bytes_avail; + metadata_bytes -= bytes_used; + mp += bytes_used; + if (metadata_bytes == 0) + eof = 1; + break; +#ifdef HAVE_ZLIB_H + case 8: /* Deflate compression. */ + { + int r; + + ret = zip_deflate_init(a, zip); + if (ret != ARCHIVE_OK) + goto exit_mac_metadata; + zip->stream.next_in = + (Bytef *)(uintptr_t)(const void *)p; + zip->stream.avail_in = (uInt)bytes_avail; + zip->stream.total_in = 0; + zip->stream.next_out = mp; + zip->stream.avail_out = (uInt)metadata_bytes; + zip->stream.total_out = 0; + + r = inflate(&zip->stream, 0); + switch (r) { + case Z_OK: + break; + case Z_STREAM_END: + eof = 1; + break; + case Z_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Out of memory for ZIP decompression"); + ret = ARCHIVE_FATAL; + goto exit_mac_metadata; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "ZIP decompression failed (%d)", r); + ret = ARCHIVE_FATAL; + goto exit_mac_metadata; + } + bytes_used = zip->stream.total_in; + metadata_bytes -= zip->stream.total_out; + mp += zip->stream.total_out; + break; + } +#endif + default: + bytes_used = 0; + break; + } + zip_read_consume(a, bytes_used); + remaining_bytes -= bytes_used; + } + archive_entry_copy_mac_metadata(entry, metadata, + (size_t)rsrc->uncompressed_size - metadata_bytes); + + __archive_read_seek(a, offset, SEEK_SET); + zip->offset = offset; +exit_mac_metadata: + zip->decompress_init = 0; + free(metadata); + return (ret); +} + static int archive_read_format_zip_seekable_read_header(struct archive_read *a, struct archive_entry *entry) { struct zip *zip = (struct zip *)a->format->data; - int r; + struct zip_entry *rsrc; + int r, ret = ARCHIVE_OK; a->archive.archive_format = ARCHIVE_FORMAT_ZIP; if (a->archive.archive_format_name == NULL) @@ -344,26 +702,45 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a, zip->entries_remaining = zip->central_directory_entries; if (r != ARCHIVE_OK) return r; - zip->entry = zip->zip_entries; - } else { - ++zip->entry; + /* Get first entry whose local header offset is lower than + * other entries in the archive file. */ + zip->entry = + (struct zip_entry *)ARCHIVE_RB_TREE_MIN(&zip->tree); + } else if (zip->entry != NULL) { + /* Get next entry in local header offset order. */ + zip->entry = (struct zip_entry *)__archive_rb_tree_iterate( + &zip->tree, &zip->entry->node, ARCHIVE_RB_DIR_RIGHT); } - if (zip->entries_remaining <= 0) + if (zip->entries_remaining <= 0 || zip->entry == NULL) return ARCHIVE_EOF; --zip->entries_remaining; - /* TODO: If entries are sorted by offset within the file, we - should be able to skip here instead of seeking. Skipping is - typically faster (easier for I/O layer to optimize). */ - __archive_read_seek(a, zip->entry->local_header_offset, SEEK_SET); + if (zip->entry->rsrcname.s) + rsrc = (struct zip_entry *)__archive_rb_tree_find_node( + &zip->tree_rsrc, zip->entry->rsrcname.s); + else + rsrc = NULL; + + /* File entries are sorted by the header offset, we should mostly + * use zip_read_consume to advance a read point to avoid redundant + * data reading. */ + if (zip->offset < zip->entry->local_header_offset) + zip_read_consume(a, + zip->entry->local_header_offset - zip->offset); + else if (zip->offset != zip->entry->local_header_offset) { + __archive_read_seek(a, zip->entry->local_header_offset, + SEEK_SET); + zip->offset = zip->entry->local_header_offset; + } zip->unconsumed = 0; r = zip_read_local_file_header(a, entry, zip); if (r != ARCHIVE_OK) return r; if ((zip->entry->mode & AE_IFMT) == AE_IFLNK) { const void *p; - size_t linkname_length = archive_entry_size(entry); + struct archive_string_conv *sconv; + size_t linkname_length = (size_t)archive_entry_size(entry); archive_entry_set_size(entry, 0); p = __archive_read_ahead(a, linkname_length, NULL); @@ -373,17 +750,45 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a, return ARCHIVE_FATAL; } + sconv = zip->sconv; + if (sconv == NULL && (zip->entry->flags & ZIP_UTF8_NAME)) + sconv = zip->sconv_utf8; + if (sconv == NULL) + sconv = zip->sconv_default; if (archive_entry_copy_symlink_l(entry, p, linkname_length, - NULL) != 0) { - /* NOTE: If the last argument is NULL, this will - * fail only by memeory allocation failure. */ - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for Symlink"); - return (ARCHIVE_FATAL); + sconv) != 0) { + if (errno != ENOMEM && sconv == zip->sconv_utf8 && + (zip->entry->flags & ZIP_UTF8_NAME)) + archive_entry_copy_symlink_l(entry, p, + linkname_length, NULL); + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Symlink"); + return (ARCHIVE_FATAL); + } + /* + * Since there is no character-set regulation for + * symlink name, do not report the conversion error + * in an automatic conversion. + */ + if (sconv != zip->sconv_utf8 || + (zip->entry->flags & ZIP_UTF8_NAME) == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Symlink cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name( + sconv)); + ret = ARCHIVE_WARN; + } } - /* TODO: handle character-set issues? */ } - return ARCHIVE_OK; + if (rsrc) { + int ret2 = zip_read_mac_metadata(a, entry, rsrc); + if (ret2 < ret) + ret = ret2; + } + return (ret); } static int @@ -410,6 +815,11 @@ archive_read_format_zip_streamable_bid(struct archive_read *a, int best_bid) return (30); } + /* TODO: It's worth looking ahead a little bit for a valid + * PK signature. In particular, that would make it possible + * to read some UUEncoded SFX files or SFX files coming from + * a network socket. */ + return (0); } @@ -424,11 +834,12 @@ archive_read_format_zip_options(struct archive_read *a, if (strcmp(key, "compat-2x") == 0) { /* Handle filnames as libarchive 2.x */ zip->init_default_conversion = (val != NULL) ? 1 : 0; - ret = ARCHIVE_OK; + return (ARCHIVE_OK); } else if (strcmp(key, "hdrcharset") == 0) { if (val == NULL || val[0] == 0) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "zip: hdrcharset option needs a character-set name"); + "zip: hdrcharset option needs a character-set name" + ); else { zip->sconv = archive_string_conversion_from_charset( &a->archive, val, 0); @@ -439,11 +850,13 @@ archive_read_format_zip_options(struct archive_read *a, } else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "zip: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -462,7 +875,8 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a, if (zip->zip_entries == NULL) { zip->zip_entries = malloc(sizeof(struct zip_entry)); if (zip->zip_entries == NULL) { - archive_set_error(&a->archive, ENOMEM, "Out of memory"); + archive_set_error(&a->archive, ENOMEM, + "Out of memory"); return ARCHIVE_FATAL; } } @@ -470,7 +884,7 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a, memset(zip->entry, 0, sizeof(struct zip_entry)); /* Search ahead for the next local file header. */ - __archive_read_consume(a, zip->unconsumed); + zip_read_consume(a, zip->unconsumed); zip->unconsumed = 0; for (;;) { int64_t skipped = 0; @@ -490,8 +904,9 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a, if (p[2] == '\003' && p[3] == '\004') { /* Regular file entry. */ - __archive_read_consume(a, skipped); - return zip_read_local_file_header(a, entry, zip); + zip_read_consume(a, skipped); + return zip_read_local_file_header(a, + entry, zip); } if (p[2] == '\005' && p[3] == '\006') @@ -501,8 +916,31 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a, ++p; ++skipped; } - __archive_read_consume(a, skipped); + zip_read_consume(a, skipped); + } +} + +static ssize_t +zip_get_local_file_header_size(struct archive_read *a, size_t extra) +{ + const char *p; + ssize_t filename_length, extra_length; + + if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return (ARCHIVE_WARN); + } + p += extra; + + if (memcmp(p, "PK\003\004", 4) != 0) { + archive_set_error(&a->archive, -1, "Damaged Zip archive"); + return ARCHIVE_WARN; } + filename_length = archive_le16dec(p + 26); + extra_length = archive_le16dec(p + 28); + + return (30 + filename_length + extra_length); } /* @@ -550,7 +988,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, version = p[4]; zip_entry->system = p[5]; zip_entry->flags = archive_le16dec(p + 6); - zip_entry->compression = archive_le16dec(p + 8); + zip_entry->compression = (char)archive_le16dec(p + 8); zip_entry->mtime = zip_time(p + 10); local_crc32 = archive_le32dec(p + 14); compressed_size = archive_le32dec(p + 18); @@ -558,11 +996,11 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, filename_length = archive_le16dec(p + 26); extra_length = archive_le16dec(p + 28); - __archive_read_consume(a, 30); + zip_read_consume(a, 30); if (zip->have_central_directory) { - /* If we read the central dir entry, we must have size information - as well, so ignore the length-at-end flag. */ + /* If we read the central dir entry, we must have size + * information as well, so ignore the length-at-end flag. */ zip_entry->flags &= ~ZIP_LENGTH_AT_END; /* If we have values from both the local file header and the central directory, warn about mismatches @@ -570,19 +1008,22 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, writers always put zero in the local header; don't bother warning about that. */ if (local_crc32 != 0 && local_crc32 != zip_entry->crc32) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Inconsistent CRC32 values"); ret = ARCHIVE_WARN; } if (compressed_size != 0 && compressed_size != zip_entry->compressed_size) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Inconsistent compressed size"); ret = ARCHIVE_WARN; } if (uncompressed_size != 0 && uncompressed_size != zip_entry->uncompressed_size) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Inconsistent uncompressed size"); ret = ARCHIVE_WARN; } @@ -628,7 +1069,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, archive_string_conversion_charset_name(sconv)); ret = ARCHIVE_WARN; } - __archive_read_consume(a, filename_length); + zip_read_consume(a, filename_length); if (zip_entry->mode == 0) { /* Especially in streaming mode, we can end up @@ -640,14 +1081,14 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, if (len > 0 && wp[len - 1] == L'/') zip_entry->mode = AE_IFDIR | 0777; else - zip_entry->mode = AE_IFREG | 0777; + zip_entry->mode = AE_IFREG | 0666; } else { cp = archive_entry_pathname(entry); len = (cp != NULL)?strlen(cp):0; if (len > 0 && cp[len - 1] == '/') zip_entry->mode = AE_IFDIR | 0777; else - zip_entry->mode = AE_IFREG | 0777; + zip_entry->mode = AE_IFREG | 0666; } } @@ -658,7 +1099,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_FATAL); } process_extra(h, extra_length, zip_entry); - __archive_read_consume(a, extra_length); + zip_read_consume(a, extra_length); /* Populate some additional entry fields: */ archive_entry_set_mode(entry, zip_entry->mode); @@ -702,8 +1143,8 @@ compression_name(int compression) "deflation" }; - if (compression < - sizeof(compression_names)/sizeof(compression_names[0])) + if (0 <= compression && compression < + (int)(sizeof(compression_names)/sizeof(compression_names[0]))) return compression_names[compression]; else return "??"; @@ -755,7 +1196,7 @@ archive_read_format_zip_read_data(struct archive_read *a, return (ARCHIVE_FAILED); } - __archive_read_consume(a, zip->unconsumed); + zip_read_consume(a, zip->unconsumed); zip->unconsumed = 0; switch(zip->entry->compression) { @@ -781,13 +1222,16 @@ archive_read_format_zip_read_data(struct archive_read *a, return (r); /* Update checksum */ if (*size) - zip->entry_crc32 = crc32(zip->entry_crc32, *buff, *size); + zip->entry_crc32 = crc32(zip->entry_crc32, *buff, + (unsigned)*size); /* If we hit the end, swallow any end-of-data marker. */ if (zip->end_of_entry) { /* Check file size, CRC against these values. */ - if (zip->entry->compressed_size != zip->entry_compressed_bytes_read) { + if (zip->entry->compressed_size != + zip->entry_compressed_bytes_read) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "ZIP compressed data is wrong size (read %jd, expected %jd)", + "ZIP compressed data is wrong size " + "(read %jd, expected %jd)", (intmax_t)zip->entry_compressed_bytes_read, (intmax_t)zip->entry->compressed_size); return (ARCHIVE_WARN); @@ -797,7 +1241,8 @@ archive_read_format_zip_read_data(struct archive_read *a, if ((zip->entry->uncompressed_size & UINT32_MAX) != (zip->entry_uncompressed_bytes_read & UINT32_MAX)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "ZIP uncompressed data is wrong size (read %jd, expected %jd)", + "ZIP uncompressed data is wrong size " + "(read %jd, expected %jd)", (intmax_t)zip->entry_uncompressed_bytes_read, (intmax_t)zip->entry->uncompressed_size); return (ARCHIVE_WARN); @@ -846,6 +1291,8 @@ zip_read_data_none(struct archive_read *a, const void **_buff, const char *buff; ssize_t bytes_avail; + (void)offset; /* UNUSED */ + zip = (struct zip *)(a->format->data); if (zip->entry->flags & ZIP_LENGTH_AT_END) { @@ -858,7 +1305,8 @@ zip_read_data_none(struct archive_read *a, const void **_buff, that are longer than this, so a failure to get at least 16 bytes really does indicate a truncated file. */ - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file data"); return (ARCHIVE_FATAL); } @@ -867,8 +1315,10 @@ zip_read_data_none(struct archive_read *a, const void **_buff, if (p[0] == 'P' && p[1] == 'K' && p[2] == '\007' && p[3] == '\010' && archive_le32dec(p + 4) == zip->entry_crc32 - && archive_le32dec(p + 8) == zip->entry_compressed_bytes_read - && archive_le32dec(p + 12) == zip->entry_uncompressed_bytes_read) { + && archive_le32dec(p + 8) == + zip->entry_compressed_bytes_read + && archive_le32dec(p + 12) == + zip->entry_uncompressed_bytes_read) { zip->entry->crc32 = archive_le32dec(p + 4); zip->entry->compressed_size = archive_le32dec(p + 8); zip->entry->uncompressed_size = archive_le32dec(p + 12); @@ -879,9 +1329,10 @@ zip_read_data_none(struct archive_read *a, const void **_buff, /* If not at EOF, ensure we consume at least one byte. */ ++p; - /* Scan forward until we see where a PK\007\010 signature might be. */ - /* Return bytes up until that point. On the next call, the code - above will verify the data descriptor. */ + /* Scan forward until we see where a PK\007\010 signature + * might be. */ + /* Return bytes up until that point. On the next call, + * the code above will verify the data descriptor. */ while (p < buff + bytes_avail - 4) { if (p[3] == 'P') { p += 3; } else if (p[3] == 'K') { p += 2; } @@ -900,12 +1351,13 @@ zip_read_data_none(struct archive_read *a, const void **_buff, /* Grab a bunch of bytes. */ buff = __archive_read_ahead(a, 1, &bytes_avail); if (bytes_avail <= 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file data"); return (ARCHIVE_FATAL); } if (bytes_avail > zip->entry_bytes_remaining) - bytes_avail = zip->entry_bytes_remaining; + bytes_avail = (ssize_t)zip->entry_bytes_remaining; } *size = bytes_avail; zip->entry_bytes_remaining -= bytes_avail; @@ -918,6 +1370,31 @@ zip_read_data_none(struct archive_read *a, const void **_buff, #ifdef HAVE_ZLIB_H static int +zip_deflate_init(struct archive_read *a, struct zip *zip) +{ + int r; + + /* If we haven't yet read any data, initialize the decompressor. */ + if (!zip->decompress_init) { + if (zip->stream_valid) + r = inflateReset(&zip->stream); + else + r = inflateInit2(&zip->stream, + -15 /* Don't check for zlib header */); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize ZIP decompression."); + return (ARCHIVE_FATAL); + } + /* Stream structure has been set up. */ + zip->stream_valid = 1; + /* We've initialized decompression for this stream. */ + zip->decompress_init = 1; + } + return (ARCHIVE_OK); +} + +static int zip_read_data_deflate(struct archive_read *a, const void **buff, size_t *size, int64_t *offset) { @@ -926,6 +1403,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, const void *compressed_buff; int r; + (void)offset; /* UNUSED */ + zip = (struct zip *)(a->format->data); /* If the buffer hasn't been allocated, allocate it now. */ @@ -940,23 +1419,9 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, } } - /* If we haven't yet read any data, initialize the decompressor. */ - if (!zip->decompress_init) { - if (zip->stream_valid) - r = inflateReset(&zip->stream); - else - r = inflateInit2(&zip->stream, - -15 /* Don't check for zlib header */); - if (r != Z_OK) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Can't initialize ZIP decompression."); - return (ARCHIVE_FATAL); - } - /* Stream structure has been set up. */ - zip->stream_valid = 1; - /* We've initialized decompression for this stream. */ - zip->decompress_init = 1; - } + r = zip_deflate_init(a, zip); + if (r != ARCHIVE_OK) + return (r); /* * Note: '1' here is a performance optimization. @@ -967,7 +1432,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, compressed_buff = __archive_read_ahead(a, 1, &bytes_avail); if (0 == (zip->entry->flags & ZIP_LENGTH_AT_END) && bytes_avail > zip->entry_bytes_remaining) { - bytes_avail = zip->entry_bytes_remaining; + bytes_avail = (ssize_t)zip->entry_bytes_remaining; } if (bytes_avail <= 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -982,10 +1447,10 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, * cast to remove 'const'. */ zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff; - zip->stream.avail_in = bytes_avail; + zip->stream.avail_in = (uInt)bytes_avail; zip->stream.total_in = 0; zip->stream.next_out = zip->uncompressed_buffer; - zip->stream.avail_out = zip->uncompressed_buffer_size; + zip->stream.avail_out = (uInt)zip->uncompressed_buffer_size; zip->stream.total_out = 0; r = inflate(&zip->stream, 0); @@ -1007,7 +1472,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, /* Consume as much as the compressor actually used. */ bytes_avail = zip->stream.total_in; - __archive_read_consume(a, bytes_avail); + zip_read_consume(a, bytes_avail); zip->entry_bytes_remaining -= bytes_avail; zip->entry_compressed_bytes_read += bytes_avail; @@ -1025,7 +1490,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, return (ARCHIVE_FATAL); } /* Consume the optional PK\007\010 marker. */ - if (p[0] == 'P' && p[1] == 'K' && p[2] == '\007' && p[3] == '\010') { + if (p[0] == 'P' && p[1] == 'K' && + p[2] == '\007' && p[3] == '\010') { zip->entry->crc32 = archive_le32dec(p + 4); zip->entry->compressed_size = archive_le32dec(p + 8); zip->entry->uncompressed_size = archive_le32dec(p + 12); @@ -1047,14 +1513,11 @@ archive_read_format_zip_read_data_skip(struct archive_read *a) /* If we've already read to end of data, we're done. */ if (zip->end_of_entry) return (ARCHIVE_OK); - /* If we're seeking, we're done. */ - if (zip->have_central_directory) - return (ARCHIVE_OK); /* So we know we're streaming... */ if (0 == (zip->entry->flags & ZIP_LENGTH_AT_END)) { /* We know the compressed length, so we can just skip. */ - int64_t bytes_skipped = __archive_read_consume(a, + int64_t bytes_skipped = zip_read_consume(a, zip->entry_bytes_remaining + zip->unconsumed); if (bytes_skipped < 0) return (ARCHIVE_FATAL); @@ -1077,36 +1540,36 @@ archive_read_format_zip_read_data_skip(struct archive_read *a) if (r != ARCHIVE_OK) return (r); } - break; + return ARCHIVE_OK; #endif default: /* Uncompressed or unknown. */ /* Scan for a PK\007\010 signature. */ - __archive_read_consume(a, zip->unconsumed); + zip_read_consume(a, zip->unconsumed); zip->unconsumed = 0; for (;;) { const char *p, *buff; ssize_t bytes_avail; buff = __archive_read_ahead(a, 16, &bytes_avail); if (bytes_avail < 16) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file data"); return (ARCHIVE_FATAL); } p = buff; - while (p < buff + bytes_avail - 16) { + while (p <= buff + bytes_avail - 16) { if (p[3] == 'P') { p += 3; } else if (p[3] == 'K') { p += 2; } else if (p[3] == '\007') { p += 1; } else if (p[3] == '\010' && p[2] == '\007' && p[1] == 'K' && p[0] == 'P') { - __archive_read_consume(a, p - buff + 16); + zip_read_consume(a, p - buff + 16); return ARCHIVE_OK; } else { p += 4; } } - __archive_read_consume(a, p - buff); + zip_read_consume(a, p - buff); } } - return ARCHIVE_OK; } static int @@ -1119,6 +1582,11 @@ archive_read_format_zip_cleanup(struct archive_read *a) if (zip->stream_valid) inflateEnd(&zip->stream); #endif + if (zip->zip_entries && zip->central_directory_entries) { + unsigned i; + for (i = 0; i < zip->central_directory_entries; i++) + archive_string_free(&(zip->zip_entries[i].rsrcname)); + } free(zip->zip_entries); free(zip->uncompressed_buffer); archive_string_free(&(zip->extra)); @@ -1201,11 +1669,14 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) /* Info-ZIP Unix Extra Field (old version) "UX". */ if (datasize >= 8) { zip_entry->atime = archive_le32dec(p + offset); - zip_entry->mtime = archive_le32dec(p + offset + 4); + zip_entry->mtime = + archive_le32dec(p + offset + 4); } if (datasize >= 12) { - zip_entry->uid = archive_le16dec(p + offset + 8); - zip_entry->gid = archive_le16dec(p + offset + 10); + zip_entry->uid = + archive_le16dec(p + offset + 8); + zip_entry->gid = + archive_le16dec(p + offset + 10); } break; } @@ -1219,7 +1690,8 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) if (datasize >= 2) zip_entry->uid = archive_le16dec(p + offset); if (datasize >= 4) - zip_entry->gid = archive_le16dec(p + offset + 2); + zip_entry->gid = + archive_le16dec(p + offset + 2); break; case 0x7875: { @@ -1231,22 +1703,26 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) /* get a uid size. */ uidsize = p[offset+1]; if (uidsize == 2) - zip_entry->uid = archive_le16dec( - p + offset + 2); + zip_entry->uid = + archive_le16dec( + p + offset + 2); else if (uidsize == 4 && datasize >= 6) - zip_entry->uid = archive_le32dec( - p + offset + 2); + zip_entry->uid = + archive_le32dec( + p + offset + 2); } if (datasize >= (2 + uidsize + 3)) { /* get a gid size. */ gidsize = p[offset+2+uidsize]; if (gidsize == 2) - zip_entry->gid = archive_le16dec( - p+offset+2+uidsize+1); + zip_entry->gid = + archive_le16dec( + p+offset+2+uidsize+1); else if (gidsize == 4 && datasize >= (2 + uidsize + 5)) - zip_entry->gid = archive_le32dec( - p+offset+2+uidsize+1); + zip_entry->gid = + archive_le32dec( + p+offset+2+uidsize+1); } } break; diff --git a/Utilities/cmlibarchive/libarchive/archive_string.c b/Utilities/cmlibarchive/libarchive/archive_string.c index cbfad2c5b..87f9288f1 100644 --- a/Utilities/cmlibarchive/libarchive/archive_string.c +++ b/Utilities/cmlibarchive/libarchive/archive_string.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2011 Tim Kientzle - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,9 +61,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_string.c 201095 2009-12-28 02:33 #include <windows.h> #include <locale.h> #endif -#if defined(__APPLE__) -#include <CoreServices/CoreServices.h> -#endif #include "archive_endian.h" #include "archive_private.h" @@ -115,11 +112,6 @@ struct archive_string_conv { #endif /* A temporary buffer for normalization. */ struct archive_string utftmp; -#if defined(__APPLE__) - UnicodeToTextInfo uniInfo; - struct archive_string utf16nfc; - struct archive_string utf16nfd; -#endif int (*converter[2])(struct archive_string *, const void *, size_t, struct archive_string_conv *); int nconverter; @@ -164,29 +156,29 @@ static int archive_string_append_from_wcs_in_codepage(struct archive_string *, static int is_big_endian(void); static int strncat_in_codepage(struct archive_string *, const void *, size_t, struct archive_string_conv *); -static int win_strncat_from_utf16be(struct archive_string *, const void *, size_t, - struct archive_string_conv *); -static int win_strncat_from_utf16le(struct archive_string *, const void *, size_t, - struct archive_string_conv *); -static int win_strncat_to_utf16be(struct archive_string *, const void *, size_t, - struct archive_string_conv *); -static int win_strncat_to_utf16le(struct archive_string *, const void *, size_t, - struct archive_string_conv *); -#endif -static int best_effort_strncat_from_utf16be(struct archive_string *, const void *, +static int win_strncat_from_utf16be(struct archive_string *, const void *, size_t, struct archive_string_conv *); -static int best_effort_strncat_from_utf16le(struct archive_string *, const void *, +static int win_strncat_from_utf16le(struct archive_string *, const void *, size_t, struct archive_string_conv *); -static int best_effort_strncat_to_utf16be(struct archive_string *, const void *, +static int win_strncat_to_utf16be(struct archive_string *, const void *, size_t, struct archive_string_conv *); -static int best_effort_strncat_to_utf16le(struct archive_string *, const void *, +static int win_strncat_to_utf16le(struct archive_string *, const void *, size_t, struct archive_string_conv *); +#endif +static int best_effort_strncat_from_utf16be(struct archive_string *, + const void *, size_t, struct archive_string_conv *); +static int best_effort_strncat_from_utf16le(struct archive_string *, + const void *, size_t, struct archive_string_conv *); +static int best_effort_strncat_to_utf16be(struct archive_string *, + const void *, size_t, struct archive_string_conv *); +static int best_effort_strncat_to_utf16le(struct archive_string *, + const void *, size_t, struct archive_string_conv *); #if defined(HAVE_ICONV) static int iconv_strncat_in_locale(struct archive_string *, const void *, size_t, struct archive_string_conv *); #endif -static int best_effort_strncat_in_locale(struct archive_string *, const void *, - size_t, struct archive_string_conv *); +static int best_effort_strncat_in_locale(struct archive_string *, + const void *, size_t, struct archive_string_conv *); static int _utf8_to_unicode(uint32_t *, const char *, size_t); static int utf8_to_unicode(uint32_t *, const char *, size_t); static inline uint32_t combine_surrogate_pair(uint32_t, uint32_t); @@ -201,10 +193,8 @@ static int strncat_from_utf8_to_utf8(struct archive_string *, const void *, size_t, struct archive_string_conv *); static int archive_string_normalize_C(struct archive_string *, const void *, size_t, struct archive_string_conv *); -#if defined(__APPLE__) static int archive_string_normalize_D(struct archive_string *, const void *, size_t, struct archive_string_conv *); -#endif static int archive_string_append_unicode(struct archive_string *, const void *, size_t, struct archive_string_conv *); @@ -238,7 +228,8 @@ archive_string_concat(struct archive_string *dest, struct archive_string *src) } void -archive_wstring_concat(struct archive_wstring *dest, struct archive_wstring *src) +archive_wstring_concat(struct archive_wstring *dest, + struct archive_wstring *src) { if (archive_wstring_append(dest, src->s, src->length) == NULL) __archive_errx(1, "Out of memory"); @@ -443,10 +434,7 @@ int archive_wstring_append_from_mbs(struct archive_wstring *dest, const char *p, size_t len) { - int r = archive_wstring_append_from_mbs_in_codepage(dest, p, len, NULL); - if (r != 0 && errno == ENOMEM) - __archive_errx(1, "No memory"); - return (r); + return archive_wstring_append_from_mbs_in_codepage(dest, p, len, NULL); } static int @@ -479,7 +467,8 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest, *ws++ = (wchar_t)*mp++; count++; } - } else if (sc != NULL && (sc->flag & SCONV_NORMALIZATION_C)) { + } else if (sc != NULL && + (sc->flag & (SCONV_NORMALIZATION_C | SCONV_NORMALIZATION_D))) { /* * Normalize UTF-8 and UTF-16BE and convert it directly * to UTF-16 as wchar_t. @@ -495,31 +484,36 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest, if (sc->flag & SCONV_FROM_UTF16) { /* * UTF-16BE/LE NFD ===> UTF-16 NFC + * UTF-16BE/LE NFC ===> UTF-16 NFD */ - count = utf16nbytes(s, length); + count = (int)utf16nbytes(s, length); } else { /* * UTF-8 NFD ===> UTF-16 NFC + * UTF-8 NFC ===> UTF-16 NFD */ - count = mbsnbytes(s, length); + count = (int)mbsnbytes(s, length); } u16.s = (char *)dest->s; u16.length = dest->length << 1;; u16.buffer_length = dest->buffer_length; - ret = archive_string_normalize_C(&u16, s, count, sc); + if (sc->flag & SCONV_NORMALIZATION_C) + ret = archive_string_normalize_C(&u16, s, count, sc); + else + ret = archive_string_normalize_D(&u16, s, count, sc); dest->s = (wchar_t *)u16.s; dest->length = u16.length >> 1; dest->buffer_length = u16.buffer_length; sc->flag = saved_flag;/* restore the saved flag. */ return (ret); } else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) { - count = utf16nbytes(s, length); + count = (int)utf16nbytes(s, length); count >>= 1; /* to be WCS length */ /* Allocate memory for WCS. */ if (NULL == archive_wstring_ensure(dest, dest->length + count + 1)) return (-1); - wmemcpy(dest->s + dest->length, (wchar_t *)s, count); + wmemcpy(dest->s + dest->length, (const wchar_t *)s, count); if ((sc->flag & SCONV_FROM_UTF16BE) && !is_big_endian()) { uint16_t *u16 = (uint16_t *)(dest->s + dest->length); int b; @@ -537,6 +531,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest, } } else { DWORD mbflag; + size_t buffsize; if (sc == NULL) mbflag = 0; @@ -548,83 +543,30 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest, } else mbflag = MB_PRECOMPOSED; - if (length == 0) { - /* - * We do not need to convert any characters but make - * sure `dest' has a valid buffer(no NULL pointer). - */ - if (NULL == archive_wstring_ensure(dest, - dest->length + 1)) + buffsize = dest->length + length + 1; + do { + /* Allocate memory for WCS. */ + if (NULL == archive_wstring_ensure(dest, buffsize)) return (-1); - dest->s[dest->length] = L'\0'; - return (0); - } - - /* - * Count how many bytes are needed for WCS. - */ - count = MultiByteToWideChar(from_cp, - mbflag, s, length, NULL, 0); - if (count == 0) { - if (dest->s == NULL) { - if (NULL == archive_wstring_ensure(dest, - dest->length + 1)) - return (-1); + /* Convert MBS to WCS. */ + count = MultiByteToWideChar(from_cp, + mbflag, s, (int)length, dest->s + dest->length, + (int)(dest->buffer_length >> 1) -1); + if (count == 0 && + GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + /* Expand the WCS buffer. */ + buffsize = dest->buffer_length << 1; + continue; } - dest->s[dest->length] = L'\0'; - return (-1); - } - /* Allocate memory for WCS. */ - if (NULL == archive_wstring_ensure(dest, - dest->length + count + 1)) - return (-1); - /* Convert MBS to WCS. */ - count = MultiByteToWideChar(from_cp, - mbflag, s, length, dest->s + dest->length, count); - if (count == 0) - ret = -1; + if (count == 0 && length != 0) + ret = -1; + } while (0); } dest->length += count; dest->s[dest->length] = L'\0'; return (ret); } -#elif defined(HAVE_MBSNRTOWCS) - -/* - * Convert MBS to WCS. - * Note: returns -1 if conversion fails. - */ -int -archive_wstring_append_from_mbs(struct archive_wstring *dest, - const char *p, size_t len) -{ - size_t r; - /* - * No single byte will be more than one wide character, - * so this length estimate will always be big enough. - */ - size_t wcs_length = len; - size_t mbs_length = len; - const char *mbs = p; - wchar_t *wcs; - mbstate_t shift_state; - - memset(&shift_state, 0, sizeof(shift_state)); - if (NULL == archive_wstring_ensure(dest, dest->length + wcs_length + 1)) - __archive_errx(1, - "No memory for archive_wstring_append_from_mbs()"); - wcs = dest->s + dest->length; - r = mbsnrtowcs(wcs, &mbs, mbs_length, wcs_length, &shift_state); - if (r != (size_t)-1) { - dest->length += r; - dest->s[dest->length] = L'\0'; - return (0); - } - dest->s[dest->length] = L'\0'; - return (-1); -} - #else /* @@ -636,6 +578,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest, const char *p, size_t len) { size_t r; + int ret_val = 0; /* * No single byte will be more than one wide character, * so this length estimate will always be big enough. @@ -650,23 +593,36 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest, memset(&shift_state, 0, sizeof(shift_state)); #endif if (NULL == archive_wstring_ensure(dest, dest->length + wcs_length + 1)) - __archive_errx(1, - "No memory for archive_wstring_append_from_mbs()"); + return (-1); wcs = dest->s + dest->length; /* * We cannot use mbsrtowcs/mbstowcs here because those may convert * extra MBS when strlen(p) > len and one wide character consis of * multi bytes. */ - while (wcs_length > 0 && *mbs && mbs_length > 0) { + while (*mbs && mbs_length > 0) { + if (wcs_length == 0) { + dest->length = wcs - dest->s; + dest->s[dest->length] = L'\0'; + wcs_length = mbs_length; + if (NULL == archive_wstring_ensure(dest, + dest->length + wcs_length + 1)) + return (-1); + wcs = dest->s + dest->length; + } #if HAVE_MBRTOWC r = mbrtowc(wcs, mbs, wcs_length, &shift_state); #else r = mbtowc(wcs, mbs, wcs_length); #endif if (r == (size_t)-1 || r == (size_t)-2) { - dest->s[dest->length] = L'\0'; - return (-1); + ret_val = -1; + if (errno == EILSEQ) { + ++mbs; + --mbs_length; + continue; + } else + break; } if (r == 0 || r > mbs_length) break; @@ -677,7 +633,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest, } dest->length = wcs - dest->s; dest->s[dest->length] = L'\0'; - return (0); + return (ret_val); } #endif @@ -697,10 +653,7 @@ int archive_string_append_from_wcs(struct archive_string *as, const wchar_t *w, size_t len) { - int r = archive_string_append_from_wcs_in_codepage(as, w, len, NULL); - if (r != 0 && errno == ENOMEM) - __archive_errx(1, "No memory"); - return (r); + return archive_string_append_from_wcs_in_codepage(as, w, len, NULL); } static int @@ -774,7 +727,7 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as, else dp = &defchar_used; count = WideCharToMultiByte(to_cp, 0, ws, wslen, - as->s + as->length, as->buffer_length-1, NULL, dp); + as->s + as->length, (int)as->buffer_length-1, NULL, dp); if (count == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { /* Expand the MBS buffer and retry. */ @@ -792,73 +745,6 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as, return (defchar_used?-1:ret); } -#elif defined(HAVE_WCSNRTOMBS) - -/* - * Translates a wide character string into current locale character set - * and appends to the archive_string. Note: returns -1 if conversion - * fails. - */ -int -archive_string_append_from_wcs(struct archive_string *as, - const wchar_t *w, size_t len) -{ - mbstate_t shift_state; - size_t r, ndest, nwc; - char *dest; - const wchar_t *wp, *wpp; - int ret_val = 0; - - wp = w; - nwc = len; - ndest = len * 2; - /* Initialize the shift state. */ - memset(&shift_state, 0, sizeof(shift_state)); - while (nwc > 0) { - /* Allocate buffer for MBS. */ - if (archive_string_ensure(as, as->length + ndest + 1) == NULL) - __archive_errx(1, "Out of memory"); - - dest = as->s + as->length; - wpp = wp; - r = wcsnrtombs(dest, &wp, nwc, - as->buffer_length - as->length -1, - &shift_state); - if (r == (size_t)-1) { - if (errno == EILSEQ) { - /* Retry conversion just for safe WCS. */ - size_t xwc = wp - wpp; - wp = wpp; - r = wcsnrtombs(dest, &wp, xwc, - as->buffer_length - as->length -1, - &shift_state); - if (r == (size_t)-1) - /* This would not happen. */ - return (-1); - as->length += r; - nwc -= wp - wpp; - /* Skip an illegal wide char. */ - as->s[as->length++] = '?'; - wp++; - nwc--; - ret_val = -1; - continue; - } else { - ret_val = -1; - break; - } - } - as->length += r; - if (wp == NULL || (wp - wpp) >= nwc) - break; - /* Get a remaining WCS lenth. */ - nwc -= wp - wpp; - } - /* All wide characters are translated to MBS. */ - as->s[as->length] = '\0'; - return (ret_val); -} - #elif defined(HAVE_WCTOMB) || defined(HAVE_WCRTOMB) /* @@ -893,7 +779,7 @@ archive_string_append_from_wcs(struct archive_string *as, * as->s is still NULL. */ if (archive_string_ensure(as, as->length + len + 1) == NULL) - __archive_errx(1, "Out of memory"); + return (-1); p = as->s + as->length; end = as->s + as->buffer_length - MB_CUR_MAX -1; @@ -904,7 +790,7 @@ archive_string_append_from_wcs(struct archive_string *as, /* Re-allocate buffer for MBS. */ if (archive_string_ensure(as, as->length + len * 2 + 1) == NULL) - __archive_errx(1, "Out of memory"); + return (-1); p = as->s + as->length; end = as->s + as->buffer_length - MB_CUR_MAX -1; } @@ -946,6 +832,7 @@ archive_string_append_from_wcs(struct archive_string *as, (void)as;/* UNUSED */ (void)w;/* UNUSED */ (void)len;/* UNUSED */ + errno = ENOSYS; return (-1); } @@ -987,27 +874,6 @@ add_sconv_object(struct archive *a, struct archive_string_conv *sc) *psc = sc; } -#if defined(__APPLE__) - -static int -createUniInfo(struct archive_string_conv *sconv) -{ - UnicodeMapping map; - OSStatus err; - - map.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, - kUnicodeNoSubset, kUnicode16BitFormat); - map.otherEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, - kUnicodeHFSPlusDecompVariant, kUnicode16BitFormat); - map.mappingVersion = kUnicodeUseLatestMapping; - - sconv->uniInfo = NULL; - err = CreateUnicodeToTextInfo(&map, &(sconv->uniInfo)); - return ((err == noErr)? 0: -1); -} - -#endif /* __APPLE__ */ - static void add_converter(struct archive_string_conv *sc, int (*converter) (struct archive_string *, const void *, size_t, @@ -1066,9 +932,11 @@ setup_converter(struct archive_string_conv *sc) if (sc->flag & SCONV_BEST_EFFORT) { if (sc->flag & SCONV_TO_UTF16BE) - add_converter(sc, best_effort_strncat_to_utf16be); + add_converter(sc, + best_effort_strncat_to_utf16be); else - add_converter(sc, best_effort_strncat_to_utf16le); + add_converter(sc, + best_effort_strncat_to_utf16le); } else /* Make sure we have no converter. */ sc->nconverter = 0; @@ -1082,12 +950,9 @@ setup_converter(struct archive_string_conv *sc) /* * At least we should normalize a UTF-16BE string. */ -#if defined(__APPLE__) if (sc->flag & SCONV_NORMALIZATION_D) add_converter(sc,archive_string_normalize_D); - else -#endif - if (sc->flag & SCONV_NORMALIZATION_C) + else if (sc->flag & SCONV_NORMALIZATION_C) add_converter(sc, archive_string_normalize_C); if (sc->flag & SCONV_TO_UTF8) { @@ -1135,12 +1000,9 @@ setup_converter(struct archive_string_conv *sc) /* * At least we should normalize a UTF-8 string. */ -#if defined(__APPLE__) if (sc->flag & SCONV_NORMALIZATION_D) add_converter(sc,archive_string_normalize_D); - else -#endif - if (sc->flag & SCONV_NORMALIZATION_C) + else if (sc->flag & SCONV_NORMALIZATION_C) add_converter(sc, archive_string_normalize_C); /* @@ -1174,6 +1036,16 @@ setup_converter(struct archive_string_conv *sc) #if HAVE_ICONV if (sc->cd != (iconv_t)-1) { add_converter(sc, iconv_strncat_in_locale); + /* + * iconv generally does not support UTF-8-MAC and so + * we have to the output of iconv from NFC to NFD if + * need. + */ + if ((sc->flag & SCONV_FROM_CHARSET) && + (sc->flag & SCONV_TO_UTF8)) { + if (sc->flag & SCONV_NORMALIZATION_D) + add_converter(sc, archive_string_normalize_D); + } return; } #endif @@ -1248,15 +1120,11 @@ create_sconv_object(const char *fc, const char *tc, } sc->to_charset = strdup(tc); if (sc->to_charset == NULL) { - free(sc); free(sc->from_charset); + free(sc); return (NULL); } archive_string_init(&sc->utftmp); -#if defined(__APPLE__) - archive_string_init(&sc->utf16nfc); - archive_string_init(&sc->utf16nfd); -#endif if (flag & SCONV_TO_CHARSET) { /* @@ -1286,7 +1154,7 @@ create_sconv_object(const char *fc, const char *tc, * Check if "from charset" and "to charset" are the same. */ if (strcmp(fc, tc) == 0 || - (sc->from_cp != -1 && sc->from_cp == sc->to_cp)) + (sc->from_cp != (unsigned)-1 && sc->from_cp == sc->to_cp)) sc->same = 1; else sc->same = 0; @@ -1335,13 +1203,35 @@ create_sconv_object(const char *fc, const char *tc, if ((flag & SCONV_FROM_CHARSET) && (flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8))) { #if defined(__APPLE__) - if (flag & SCONV_TO_UTF8) { - if (createUniInfo(sc) == 0) - flag |= SCONV_NORMALIZATION_D; - } else + if (flag & SCONV_TO_UTF8) + flag |= SCONV_NORMALIZATION_D; + else #endif flag |= SCONV_NORMALIZATION_C; } +#if defined(__APPLE__) + /* + * In case writing an archive file, make sure that a filename + * going to be passed to iconv is a Unicode NFC string since + * a filename in HFS Plus filesystem is a Unicode NFD one and + * iconv cannot handle it with "UTF-8" charset. It is simpler + * than a use of "UTF-8-MAC" charset. + */ + if ((flag & SCONV_TO_CHARSET) && + (flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) && + !(flag & (SCONV_TO_UTF16 | SCONV_TO_UTF8))) + flag |= SCONV_NORMALIZATION_C; + /* + * In case reading an archive file. make sure that a filename + * will be passed to users is a Unicode NFD string in order to + * correctly compare the filename with other one which comes + * from HFS Plus filesystem. + */ + if ((flag & SCONV_FROM_CHARSET) && + !(flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) && + (flag & SCONV_TO_UTF8)) + flag |= SCONV_NORMALIZATION_D; +#endif #if defined(HAVE_ICONV) sc->cd_w = (iconv_t)-1; @@ -1353,46 +1243,6 @@ create_sconv_object(const char *fc, const char *tc, (flag & SCONV_WIN_CP)) { /* This case we won't use iconv. */ sc->cd = (iconv_t)-1; -#if defined(__APPLE__) - } else if ((flag & SCONV_FROM_CHARSET) && (flag & SCONV_TO_UTF8)) { - /* - * In case reading an archive file. - * Translate non-Unicode filenames in an archive file to - * UTF-8-MAC filenames. - */ - sc->cd = iconv_open("UTF-8-MAC", fc); - if (sc->cd == (iconv_t)-1) { - if ((sc->flag & SCONV_BEST_EFFORT) && - strcmp(fc, "CP932") == 0) { - sc->cd = iconv_open("UTF-8-MAC", "SJIS"); - if (sc->cd == (iconv_t)-1) { - sc->cd = iconv_open(tc, fc); - if (sc->cd == (iconv_t)-1) - sc->cd = iconv_open(tc, "SJIS"); - } - } else - sc->cd = iconv_open(tc, fc); - } - } else if ((flag & SCONV_TO_CHARSET) && (flag & SCONV_FROM_UTF8)) { - /* - * In case writing an archive file. - * Translate UTF-8-MAC filenames in HFS Plus to non-Unicode - * filenames. - */ - sc->cd = iconv_open(tc, "UTF-8-MAC"); - if (sc->cd == (iconv_t)-1) { - if ((sc->flag & SCONV_BEST_EFFORT) && - strcmp(tc, "CP932") == 0) { - sc->cd = iconv_open("SJIS", "UTF-8-MAC"); - if (sc->cd == (iconv_t)-1) { - sc->cd = iconv_open(tc, fc); - if (sc->cd == (iconv_t)-1) - sc->cd = iconv_open("SJIS", fc); - } - } else - sc->cd = iconv_open(tc, fc); - } -#endif } else { sc->cd = iconv_open(tc, fc); if (sc->cd == (iconv_t)-1 && (sc->flag & SCONV_BEST_EFFORT)) { @@ -1428,7 +1278,7 @@ create_sconv_object(const char *fc, const char *tc, sc->flag = flag; /* - * Setup converters. + * Set up converters. */ setup_converter(sc); @@ -1450,12 +1300,6 @@ free_sconv_object(struct archive_string_conv *sc) if (sc->cd_w != (iconv_t)-1) iconv_close(sc->cd_w); #endif -#if defined(__APPLE__) - archive_string_free(&sc->utf16nfc); - archive_string_free(&sc->utf16nfd); - if (sc->uniInfo != NULL) - DisposeUnicodeToTextInfo(&(sc->uniInfo)); -#endif free(sc); } @@ -1646,7 +1490,7 @@ make_codepage_from_charset(const char *charset) * Return ANSI Code Page of current locale set by setlocale(). */ static unsigned -get_current_codepage() +get_current_codepage(void) { char *locale, *p; unsigned cp; @@ -1721,7 +1565,7 @@ static struct { * Return OEM Code Page of current locale set by setlocale(). */ static unsigned -get_current_oemcp() +get_current_oemcp(void) { int i; char *locale, *p; @@ -1750,7 +1594,7 @@ get_current_oemcp() */ static unsigned -get_current_codepage() +get_current_codepage(void) { return (-1);/* Unknown */ } @@ -1761,7 +1605,7 @@ make_codepage_from_charset(const char *charset) return (-1);/* Unknown */ } static unsigned -get_current_oemcp() +get_current_oemcp(void) { return (-1);/* Unknown */ } @@ -1995,11 +1839,37 @@ archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt) #else if ((sc->flag & SCONV_UTF8_LIBARCHIVE_2) == 0) { sc->flag |= SCONV_UTF8_LIBARCHIVE_2; - /* Re-setup string converters. */ + /* Set up string converters. */ setup_converter(sc); } #endif break; + case SCONV_SET_OPT_NORMALIZATION_C: + if ((sc->flag & SCONV_NORMALIZATION_C) == 0) { + sc->flag |= SCONV_NORMALIZATION_C; + sc->flag &= ~SCONV_NORMALIZATION_D; + /* Set up string converters. */ + setup_converter(sc); + } + break; + case SCONV_SET_OPT_NORMALIZATION_D: +#if defined(HAVE_ICONV) + /* + * If iconv will take the string, do not change the + * setting of the normalization. + */ + if (!(sc->flag & SCONV_WIN_CP) && + (sc->flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) && + !(sc->flag & (SCONV_TO_UTF16 | SCONV_TO_UTF8))) + break; +#endif + if ((sc->flag & SCONV_NORMALIZATION_D) == 0) { + sc->flag |= SCONV_NORMALIZATION_D; + sc->flag &= ~SCONV_NORMALIZATION_C; + /* Set up string converters. */ + setup_converter(sc); + } + break; default: break; } @@ -2009,8 +1879,8 @@ archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt) * * Copy one archive_string to another in locale conversion. * - * archive_strncpy_in_locale(); - * archive_strcpy_in_locale(); + * archive_strncat_l(); + * archive_strncpy_l(); * */ @@ -2056,15 +1926,15 @@ utf16nbytes(const void *_p, size_t n) } int -archive_strncpy_in_locale(struct archive_string *as, const void *_p, size_t n, +archive_strncpy_l(struct archive_string *as, const void *_p, size_t n, struct archive_string_conv *sc) { as->length = 0; - return (archive_strncat_in_locale(as, _p, n, sc)); + return (archive_strncat_l(as, _p, n, sc)); } int -archive_strncat_in_locale(struct archive_string *as, const void *_p, size_t n, +archive_strncat_l(struct archive_string *as, const void *_p, size_t n, struct archive_string_conv *sc) { const void *s; @@ -2127,7 +1997,7 @@ static int iconv_strncat_in_locale(struct archive_string *as, const void *_p, size_t length, struct archive_string_conv *sc) { - ICONV_CONST char *inp; + ICONV_CONST char *itp; size_t remaining; iconv_t cd; char *outp; @@ -2148,12 +2018,12 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p, return (-1); cd = sc->cd; - inp = (char *)(uintptr_t)_p; + itp = (char *)(uintptr_t)_p; remaining = length; outp = as->s + as->length; avail = as->buffer_length - as->length - to_size; while (remaining >= (size_t)from_size) { - size_t result = iconv(cd, &inp, &remaining, &outp, &avail); + size_t result = iconv(cd, &itp, &remaining, &outp, &avail); if (result != (size_t)-1) break; /* Conversion completed. */ @@ -2195,7 +2065,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p, *outp++ = '?'; avail--; } - inp += from_size; + itp += from_size; remaining -= from_size; return_value = -1; /* failure */ } else { @@ -2275,7 +2145,7 @@ invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc) if (codepage != CP_UTF8) mbflag |= MB_PRECOMPOSED; - if (MultiByteToWideChar(codepage, mbflag, p, n, NULL, 0) == 0) + if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0) return (-1); /* Invalid */ return (0); /* Okay */ } @@ -2332,8 +2202,8 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p, size_t length, struct archive_string_conv *sc) { size_t remaining; - char *outp; - const char *inp; + char *otp; + const uint8_t *itp; size_t avail; int return_value = 0; /* success */ @@ -2357,41 +2227,41 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p, return (-1); remaining = length; - inp = (const char *)_p; - outp = as->s + as->length; + itp = (const uint8_t *)_p; + otp = as->s + as->length; avail = as->buffer_length - as->length -1; - while (*inp && remaining > 0) { - if (*inp < 0 && (sc->flag & SCONV_TO_UTF8)) { + while (*itp && remaining > 0) { + if (*itp > 127 && (sc->flag & SCONV_TO_UTF8)) { if (avail < UTF8_R_CHAR_SIZE) { - as->length = outp - as->s; + as->length = otp - as->s; if (NULL == archive_string_ensure(as, as->buffer_length + remaining + UTF8_R_CHAR_SIZE)) return (-1); - outp = as->s + as->length; + otp = as->s + as->length; avail = as->buffer_length - as->length -1; } /* * When coping a string in UTF-8, unknown character * should be U+FFFD (replacement character). */ - UTF8_SET_R_CHAR(outp); - outp += UTF8_R_CHAR_SIZE; + UTF8_SET_R_CHAR(otp); + otp += UTF8_R_CHAR_SIZE; avail -= UTF8_R_CHAR_SIZE; - inp++; + itp++; remaining--; return_value = -1; - } else if (*inp < 0) { - *outp++ = '?'; - inp++; + } else if (*itp > 127) { + *otp++ = '?'; + itp++; remaining--; return_value = -1; } else { - *outp++ = *inp++; + *otp++ = (char)*itp++; remaining--; } } - as->length = outp - as->s; + as->length = otp - as->s; as->s[as->length] = '\0'; return (return_value); } @@ -2452,7 +2322,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) /* Invalide sequence or there are not plenty bytes. */ if ((int)n < cnt) { - cnt = n; + cnt = (int)n; for (i = 1; i < cnt; i++) { if ((s[i] & 0xc0) != 0x80) { cnt = i; @@ -2521,7 +2391,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) else cnt = 1; if ((int)n < cnt) - cnt = n; + cnt = (int)n; for (i = 1; i < cnt; i++) { if ((s[i] & 0xc0) != 0x80) { cnt = i; @@ -2577,11 +2447,12 @@ combine_surrogate_pair(uint32_t uc, uint32_t uc2) static int cesu8_to_unicode(uint32_t *pwc, const char *s, size_t n) { - uint32_t wc, wc2; + uint32_t wc = 0; int cnt; cnt = _utf8_to_unicode(&wc, s, n); if (cnt == 3 && IS_HIGH_SURROGATE_LA(wc)) { + uint32_t wc2 = 0; if (n - 3 < 3) { /* Invalid byte sequence. */ goto invalid_sequence; @@ -2773,8 +2644,8 @@ unicode_to_utf16le(char *p, size_t remaining, uint32_t uc) * If any surrogate pair are found, it would be canonicalized. */ static int -strncat_from_utf8_to_utf8(struct archive_string *as, const void *_p, size_t len, - struct archive_string_conv *sc) +strncat_from_utf8_to_utf8(struct archive_string *as, const void *_p, + size_t len, struct archive_string_conv *sc) { const char *s; char *p, *endp; @@ -3250,8 +3121,8 @@ archive_string_normalize_C(struct archive_string *as, const void *_p, /* * Remove ucx[i] by shifting - * follwoing code points. - */ + * following code points. + */ for (j = i; j+1 < ucx_size; j++) { ucx[j] = ucx[j+1]; ccx[j] = ccx[j+1]; @@ -3320,122 +3191,224 @@ archive_string_normalize_C(struct archive_string *as, const void *_p, return (ret); } -#if defined(__APPLE__) - -/* - * Normalize UTF-8 characters to Form D and copy the result. - */ static int -archive_string_normalize_D(struct archive_string *as, const void *_p, - size_t len, struct archive_string_conv *sc) +get_nfd(uint32_t *cp1, uint32_t *cp2, uint32_t uc) { - const UniChar *inp; - char *outp; - size_t newsize; - ByteCount inCount, outCount; - ByteCount inAvail, outAvail; - OSStatus err; - int ret, saved_flag; + int t, b; /* - * Convert the current string to UTF-16LE for normalization. - * The character-set of the current string must be UTF-16BE or - * UTF-8. + * These are not converted to NFD on Mac OS. */ - archive_string_empty(&(sc->utf16nfc)); - saved_flag = sc->flag;/* save a flag. */ - sc->flag &= ~(SCONV_TO_UTF16BE | SCONV_TO_UTF8); - sc->flag |= SCONV_TO_UTF16LE; - ret = archive_string_append_unicode(&(sc->utf16nfc), _p, len, sc); - sc->flag = saved_flag;/* restore the saved flag */ - if (archive_strlen(&(sc->utf16nfc)) == 0) { - if (archive_string_ensure(as, as->length + 1) == NULL) - return (-1); - return (ret); - } - + if ((uc >= 0x2000 && uc <= 0x2FFF) || + (uc >= 0xF900 && uc <= 0xFAFF) || + (uc >= 0x2F800 && uc <= 0x2FAFF)) + return (0); /* - * Normalize an NFC string to be an NFD(HFS Plus version). + * Those code points are not converted to NFD on Mac OS. + * I do not know the reason because it is undocumented. + * NFC NFD + * 1109A ==> 11099 110BA + * 1109C ==> 1109B 110BA + * 110AB ==> 110A5 110BA */ - newsize = sc->utf16nfc.length + 2; - if (archive_string_ensure(&(sc->utf16nfd), newsize) == NULL) - return (-1); + if (uc == 0x1109A || uc == 0x1109C || uc == 0x110AB) + return (0); - inp = (UniChar *)sc->utf16nfc.s; - inAvail = archive_strlen(&(sc->utf16nfc)); - sc->utf16nfd.length = 0; - outp = sc->utf16nfd.s; - outAvail = sc->utf16nfd.buffer_length -2; + t = 0; + b = sizeof(u_decomposition_table)/sizeof(u_decomposition_table[0]) -1; + while (b >= t) { + int m = (t + b) / 2; + if (u_decomposition_table[m].nfc < uc) + t = m + 1; + else if (u_decomposition_table[m].nfc > uc) + b = m - 1; + else { + *cp1 = u_decomposition_table[m].cp1; + *cp2 = u_decomposition_table[m].cp2; + return (1); + } + } + return (0); +} - do { - /* Reinitialize all state information. */ - if (ResetUnicodeToTextInfo(sc->uniInfo) != noErr) - goto return_no_changed_data; - - inCount = outCount = 0; - err = ConvertFromUnicodeToText(sc->uniInfo, - inAvail, inp, - kUnicodeDefaultDirectionMask, 0, NULL, NULL, NULL, - outAvail, &inCount, &outCount, outp); - - if (err == noErr) { - sc->utf16nfd.length = outCount; - sc->utf16nfd.s[sc->utf16nfd.length] = 0; - sc->utf16nfd.s[sc->utf16nfd.length+1] = 0; - } else if (err == kTECOutputBufferFullStatus) { - newsize = inAvail - inCount; - if (newsize > inAvail) - newsize = inAvail; - newsize += sc->utf16nfd.buffer_length + 2; - if (archive_string_ensure(&(sc->utf16nfd), newsize) - == NULL) - return (-1); - outp = sc->utf16nfd.s; - outAvail = sc->utf16nfd.buffer_length -2; - } else - goto return_no_changed_data; - } while (err == kTECOutputBufferFullStatus); +#define REPLACE_UC_WITH(cp) do { \ + uc = cp; \ + ucptr = NULL; \ +} while (0) - /* - * If there is a next-step conversion, we should convert - * a UTF-16LE(NFD) string back to the original Unicode type. - */ - saved_flag = sc->flag;/* save a flag. */ - if (!(sc->flag & - (SCONV_TO_UTF16BE | SCONV_TO_UTF16LE | SCONV_TO_UTF8))) { +/* + * Normalize UTF-8 characters to Form D and copy the result. + */ +static int +archive_string_normalize_D(struct archive_string *as, const void *_p, + size_t len, struct archive_string_conv *sc) +{ + const char *s = (const char *)_p; + char *p, *endp; + uint32_t uc, uc2; + size_t w; + int always_replace, n, n2, ret = 0, spair, ts, tm; + int (*parse)(uint32_t *, const char *, size_t); + size_t (*unparse)(char *, size_t, uint32_t); + + always_replace = 1; + ts = 1;/* text size. */ + if (sc->flag & SCONV_TO_UTF16BE) { + unparse = unicode_to_utf16be; + ts = 2; + if (sc->flag & SCONV_FROM_UTF16BE) + always_replace = 0; + } else if (sc->flag & SCONV_TO_UTF16LE) { + unparse = unicode_to_utf16le; + ts = 2; + if (sc->flag & SCONV_FROM_UTF16LE) + always_replace = 0; + } else if (sc->flag & SCONV_TO_UTF8) { + unparse = unicode_to_utf8; + if (sc->flag & SCONV_FROM_UTF8) + always_replace = 0; + } else { /* * This case is going to be converted to another * character-set through iconv. */ - if (sc->flag & SCONV_FROM_UTF16BE) - sc->flag |= SCONV_TO_UTF16BE; - else if (sc->flag & SCONV_FROM_UTF16LE) - sc->flag |= SCONV_TO_UTF16LE; + always_replace = 0; + if (sc->flag & SCONV_FROM_UTF16BE) { + unparse = unicode_to_utf16be; + ts = 2; + } else if (sc->flag & SCONV_FROM_UTF16LE) { + unparse = unicode_to_utf16le; + ts = 2; + } else { + unparse = unicode_to_utf8; + } + } + + if (sc->flag & SCONV_FROM_UTF16BE) { + parse = utf16be_to_unicode; + tm = 1; + spair = 4;/* surrogate pair size in UTF-16. */ + } else if (sc->flag & SCONV_FROM_UTF16LE) { + parse = utf16le_to_unicode; + tm = 1; + spair = 4;/* surrogate pair size in UTF-16. */ + } else { + parse = cesu8_to_unicode; + tm = ts; + spair = 6;/* surrogate pair size in UTF-8. */ + } + + if (archive_string_ensure(as, as->length + len * tm + ts) == NULL) + return (-1); + + p = as->s + as->length; + endp = as->s + as->buffer_length - ts; + while ((n = parse(&uc, s, len)) != 0) { + const char *ucptr; + uint32_t cp1, cp2; + int SIndex; + struct { + uint32_t uc; + int ccc; + } fdc[FDC_MAX]; + int fdi, fdj; + int ccc; + +check_first_code: + if (n < 0) { + /* Use a replaced unicode character. */ + UNPARSE(p, endp, uc); + s += n*-1; + len -= n*-1; + ret = -1; + continue; + } else if (n == spair || always_replace) + /* uc is converted from a surrogate pair. + * this should be treated as a changed code. */ + ucptr = NULL; else - sc->flag |= SCONV_TO_UTF8; + ucptr = s; + s += n; + len -= n; + + /* Hangul Decomposition. */ + if ((SIndex = uc - HC_SBASE) >= 0 && SIndex < HC_SCOUNT) { + int L = HC_LBASE + SIndex / HC_NCOUNT; + int V = HC_VBASE + (SIndex % HC_NCOUNT) / HC_TCOUNT; + int T = HC_TBASE + SIndex % HC_TCOUNT; + + REPLACE_UC_WITH(L); + WRITE_UC(); + REPLACE_UC_WITH(V); + WRITE_UC(); + if (T != HC_TBASE) { + REPLACE_UC_WITH(T); + WRITE_UC(); + } + continue; + } + if (IS_DECOMPOSABLE_BLOCK(uc) && CCC(uc) != 0) { + WRITE_UC(); + continue; + } + + fdi = 0; + while (get_nfd(&cp1, &cp2, uc) && fdi < FDC_MAX) { + int k; + + for (k = fdi; k > 0; k--) + fdc[k] = fdc[k-1]; + fdc[0].ccc = CCC(cp2); + fdc[0].uc = cp2; + fdi++; + REPLACE_UC_WITH(cp1); + } + + /* Read following code points. */ + while ((n2 = parse(&uc2, s, len)) > 0 && + (ccc = CCC(uc2)) != 0 && fdi < FDC_MAX) { + int j, k; + + s += n2; + len -= n2; + for (j = 0; j < fdi; j++) { + if (fdc[j].ccc > ccc) + break; + } + if (j < fdi) { + for (k = fdi; k > j; k--) + fdc[k] = fdc[k-1]; + fdc[j].ccc = ccc; + fdc[j].uc = uc2; + } else { + fdc[fdi].ccc = ccc; + fdc[fdi].uc = uc2; + } + fdi++; + } + + WRITE_UC(); + for (fdj = 0; fdj < fdi; fdj++) { + REPLACE_UC_WITH(fdc[fdj].uc); + WRITE_UC(); + } + + if (n2 == 0) + break; + REPLACE_UC_WITH(uc2); + n = n2; + goto check_first_code; } - sc->flag &= ~(SCONV_FROM_UTF16BE | SCONV_FROM_UTF8); - sc->flag |= SCONV_FROM_UTF16LE; - if (archive_string_append_unicode(as, sc->utf16nfd.s, - sc->utf16nfd.length, sc) != 0) - ret = -1; - sc->flag = saved_flag;/* restore the saved flag */ + as->length = p - as->s; + as->s[as->length] = '\0'; + if (ts == 2) + as->s[as->length+1] = '\0'; return (ret); - -return_no_changed_data: - /* - * Something conversion error happend, so we return a no normalized - * string with an error. - */ - (void)archive_string_append_unicode(as, _p, len, sc); - return (-1); } -#endif /* __APPLE__ */ - /* - * libarchive 2.x made incorrect UTF-8 strings in the wrong assumuption - * that WCS is Unicode. it is true for servel platforms but some are false. + * libarchive 2.x made incorrect UTF-8 strings in the wrong assumption + * that WCS is Unicode. It is true for several platforms but some are false. * And then people who did not use UTF-8 locale on the non Unicode WCS * platform and made a tar file with libarchive(mostly bsdtar) 2.x. Those * now cannot get right filename from libarchive 3.x and later since we @@ -3505,9 +3478,9 @@ strncat_from_utf8_libarchive2(struct archive_string *as, * Translates the wide-character into the current locale MBS. */ #if HAVE_WCRTOMB - n = wcrtomb(p, wc, &shift_state); + n = (int)wcrtomb(p, wc, &shift_state); #else - n = wctomb(p, wc); + n = (int)wctomb(p, wc); #endif if (n == -1) return (-1); @@ -3606,13 +3579,13 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes, do { defchar = 0; ll = WideCharToMultiByte(sc->to_cp, 0, - (LPCWSTR)u16, bytes>>1, mbs, mbs_size, + (LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size, NULL, &defchar); if (ll == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { /* Need more buffer for MBS. */ ll = WideCharToMultiByte(sc->to_cp, 0, - (LPCWSTR)u16, bytes, NULL, 0, NULL, NULL); + (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL); if (archive_string_ensure(as, ll +1) == NULL) return (-1); mbs = as->s + as->length; @@ -3629,15 +3602,15 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes, } static int -win_strncat_from_utf16be(struct archive_string *as, const void *_p, size_t bytes, - struct archive_string_conv *sc) +win_strncat_from_utf16be(struct archive_string *as, const void *_p, + size_t bytes, struct archive_string_conv *sc) { return (win_strncat_from_utf16(as, _p, bytes, sc, 1)); } static int -win_strncat_from_utf16le(struct archive_string *as, const void *_p, size_t bytes, - struct archive_string_conv *sc) +win_strncat_from_utf16le(struct archive_string *as, const void *_p, + size_t bytes, struct archive_string_conv *sc) { return (win_strncat_from_utf16(as, _p, bytes, sc, 0)); } @@ -3655,8 +3628,8 @@ is_big_endian(void) * Return -1 if conversion failes. */ static int -win_strncat_to_utf16(struct archive_string *as16, const void *_p, size_t length, - struct archive_string_conv *sc, int bigendian) +win_strncat_to_utf16(struct archive_string *as16, const void *_p, + size_t length, struct archive_string_conv *sc, int bigendian) { const char *s = (const char *)_p; char *u16; @@ -3689,12 +3662,12 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p, size_t length, } do { count = MultiByteToWideChar(sc->from_cp, - MB_PRECOMPOSED, s, length, (LPWSTR)u16, (int)avail>>1); + MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1); if (count == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { /* Need more buffer for UTF-16 string */ count = MultiByteToWideChar(sc->from_cp, - MB_PRECOMPOSED, s, length, NULL, 0); + MB_PRECOMPOSED, s, (int)length, NULL, 0); if (archive_string_ensure(as16, (count +1) * 2) == NULL) return (-1); @@ -3732,15 +3705,15 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p, size_t length, } static int -win_strncat_to_utf16be(struct archive_string *as16, const void *_p, size_t length, - struct archive_string_conv *sc) +win_strncat_to_utf16be(struct archive_string *as16, const void *_p, + size_t length, struct archive_string_conv *sc) { return (win_strncat_to_utf16(as16, _p, length, sc, 1)); } static int -win_strncat_to_utf16le(struct archive_string *as16, const void *_p, size_t length, - struct archive_string_conv *sc) +win_strncat_to_utf16le(struct archive_string *as16, const void *_p, + size_t length, struct archive_string_conv *sc) { return (win_strncat_to_utf16(as16, _p, length, sc, 0)); } @@ -3914,7 +3887,7 @@ archive_mstring_get_utf8(struct archive *a, struct archive_mstring *aes, sc = archive_string_conversion_to_charset(a, "UTF-8", 1); if (sc == NULL) return (-1);/* Couldn't allocate memory for sc. */ - r = archive_strncpy_in_locale(&(aes->aes_mbs), aes->aes_mbs.s, + r = archive_strncpy_l(&(aes->aes_mbs), aes->aes_mbs.s, aes->aes_mbs.length, sc); if (a == NULL) free_sconv_object(sc); @@ -4043,7 +4016,7 @@ archive_mstring_get_mbs_l(struct archive_mstring *aes, *length = aes->aes_mbs.length; return (0); } - ret = archive_strncpy_in_locale(&(aes->aes_mbs_in_locale), + ret = archive_strncpy_l(&(aes->aes_mbs_in_locale), aes->aes_mbs.s, aes->aes_mbs.length, sc); *p = aes->aes_mbs_in_locale.s; if (length != NULL) @@ -4084,7 +4057,8 @@ archive_mstring_copy_mbs_len(struct archive_mstring *aes, const char *mbs, int archive_mstring_copy_wcs(struct archive_mstring *aes, const wchar_t *wcs) { - return archive_mstring_copy_wcs_len(aes, wcs, wcs == NULL ? 0 : wcslen(wcs)); + return archive_mstring_copy_wcs_len(aes, wcs, + wcs == NULL ? 0 : wcslen(wcs)); } int @@ -4143,7 +4117,7 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes, * Translate multi-bytes from some character-set to UTF-8. */ sc->cd = sc->cd_w; - r = archive_strncpy_in_locale(&(aes->aes_utf8), mbs, len, sc); + r = archive_strncpy_l(&(aes->aes_utf8), mbs, len, sc); sc->cd = cd; if (r != 0) { aes->aes_set = 0; @@ -4175,7 +4149,7 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes, aes->aes_set = 0; } #else - r = archive_strncpy_in_locale(&(aes->aes_mbs), mbs, len, sc); + r = archive_strncpy_l(&(aes->aes_mbs), mbs, len, sc); if (r == 0) aes->aes_set = AES_SET_MBS; /* Only MBS form is set now. */ else @@ -4219,7 +4193,7 @@ archive_mstring_update_utf8(struct archive *a, struct archive_mstring *aes, sc = archive_string_conversion_from_charset(a, "UTF-8", 1); if (sc == NULL) return (-1);/* Couldn't allocate memory for sc. */ - r = archive_strcpy_in_locale(&(aes->aes_mbs), utf8, sc); + r = archive_strcpy_l(&(aes->aes_mbs), utf8, sc); if (a == NULL) free_sconv_object(sc); if (r != 0) diff --git a/Utilities/cmlibarchive/libarchive/archive_string.h b/Utilities/cmlibarchive/libarchive/archive_string.h index 0e4c9b904..23f491657 100644 --- a/Utilities/cmlibarchive/libarchive/archive_string.h +++ b/Utilities/cmlibarchive/libarchive/archive_string.h @@ -110,18 +110,20 @@ archive_string_conversion_charset_name(struct archive_string_conv *); void archive_string_conversion_set_opt(struct archive_string_conv *, int); #define SCONV_SET_OPT_UTF8_LIBARCHIVE2X 1 +#define SCONV_SET_OPT_NORMALIZATION_C 2 +#define SCONV_SET_OPT_NORMALIZATION_D 4 /* Copy one archive_string to another in locale conversion. * Return -1 if conversion failes. */ int -archive_strncpy_in_locale(struct archive_string *, const void *, size_t, +archive_strncpy_l(struct archive_string *, const void *, size_t, struct archive_string_conv *); /* Copy one archive_string to another in locale conversion. * Return -1 if conversion failes. */ int -archive_strncat_in_locale(struct archive_string *, const void *, size_t, +archive_strncat_l(struct archive_string *, const void *, size_t, struct archive_string_conv *); @@ -162,8 +164,8 @@ archive_wstrcat(struct archive_wstring *, const wchar_t *); archive_strncpy((as), (p), ((p) == NULL ? 0 : strlen(p))) #define archive_wstrcpy(as,p) \ archive_wstrncpy((as), (p), ((p) == NULL ? 0 : wcslen(p))) -#define archive_strcpy_in_locale(as,p,lo) \ - archive_strncpy_in_locale((as), (p), ((p) == NULL ? 0 : strlen(p)), (lo)) +#define archive_strcpy_l(as,p,lo) \ + archive_strncpy_l((as), (p), ((p) == NULL ? 0 : strlen(p)), (lo)) /* Copy a C string to an archive_string with limit, resizing as necessary. */ #define archive_strncpy(as,p,l) \ diff --git a/Utilities/cmlibarchive/libarchive/archive_string_composition.h b/Utilities/cmlibarchive/libarchive/archive_string_composition.h index cc4bf46c0..be41e3365 100644 --- a/Utilities/cmlibarchive/libarchive/archive_string_composition.h +++ b/Utilities/cmlibarchive/libarchive/archive_string_composition.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011 libarchive Project + * Copyright (c) 2011-2012 libarchive Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ /* * ATTENTION! * This file is generated by build/utils/gen_archive_string_composition_h.sh - * from http://unicode.org/Public/UNIDATA/UnicodeData.txt + * from http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt * * See also http://unicode.org/report/tr15/ */ @@ -1348,4 +1348,945 @@ static const unsigned char ccc_index[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,37,38,}; +struct unicode_decomposition_table { + uint32_t nfc; + uint32_t cp1; + uint32_t cp2; +}; + +static const struct unicode_decomposition_table u_decomposition_table[] = { + { 0x000C0 , 0x00041 , 0x00300 }, + { 0x000C1 , 0x00041 , 0x00301 }, + { 0x000C2 , 0x00041 , 0x00302 }, + { 0x000C3 , 0x00041 , 0x00303 }, + { 0x000C4 , 0x00041 , 0x00308 }, + { 0x000C5 , 0x00041 , 0x0030A }, + { 0x000C7 , 0x00043 , 0x00327 }, + { 0x000C8 , 0x00045 , 0x00300 }, + { 0x000C9 , 0x00045 , 0x00301 }, + { 0x000CA , 0x00045 , 0x00302 }, + { 0x000CB , 0x00045 , 0x00308 }, + { 0x000CC , 0x00049 , 0x00300 }, + { 0x000CD , 0x00049 , 0x00301 }, + { 0x000CE , 0x00049 , 0x00302 }, + { 0x000CF , 0x00049 , 0x00308 }, + { 0x000D1 , 0x0004E , 0x00303 }, + { 0x000D2 , 0x0004F , 0x00300 }, + { 0x000D3 , 0x0004F , 0x00301 }, + { 0x000D4 , 0x0004F , 0x00302 }, + { 0x000D5 , 0x0004F , 0x00303 }, + { 0x000D6 , 0x0004F , 0x00308 }, + { 0x000D9 , 0x00055 , 0x00300 }, + { 0x000DA , 0x00055 , 0x00301 }, + { 0x000DB , 0x00055 , 0x00302 }, + { 0x000DC , 0x00055 , 0x00308 }, + { 0x000DD , 0x00059 , 0x00301 }, + { 0x000E0 , 0x00061 , 0x00300 }, + { 0x000E1 , 0x00061 , 0x00301 }, + { 0x000E2 , 0x00061 , 0x00302 }, + { 0x000E3 , 0x00061 , 0x00303 }, + { 0x000E4 , 0x00061 , 0x00308 }, + { 0x000E5 , 0x00061 , 0x0030A }, + { 0x000E7 , 0x00063 , 0x00327 }, + { 0x000E8 , 0x00065 , 0x00300 }, + { 0x000E9 , 0x00065 , 0x00301 }, + { 0x000EA , 0x00065 , 0x00302 }, + { 0x000EB , 0x00065 , 0x00308 }, + { 0x000EC , 0x00069 , 0x00300 }, + { 0x000ED , 0x00069 , 0x00301 }, + { 0x000EE , 0x00069 , 0x00302 }, + { 0x000EF , 0x00069 , 0x00308 }, + { 0x000F1 , 0x0006E , 0x00303 }, + { 0x000F2 , 0x0006F , 0x00300 }, + { 0x000F3 , 0x0006F , 0x00301 }, + { 0x000F4 , 0x0006F , 0x00302 }, + { 0x000F5 , 0x0006F , 0x00303 }, + { 0x000F6 , 0x0006F , 0x00308 }, + { 0x000F9 , 0x00075 , 0x00300 }, + { 0x000FA , 0x00075 , 0x00301 }, + { 0x000FB , 0x00075 , 0x00302 }, + { 0x000FC , 0x00075 , 0x00308 }, + { 0x000FD , 0x00079 , 0x00301 }, + { 0x000FF , 0x00079 , 0x00308 }, + { 0x00100 , 0x00041 , 0x00304 }, + { 0x00101 , 0x00061 , 0x00304 }, + { 0x00102 , 0x00041 , 0x00306 }, + { 0x00103 , 0x00061 , 0x00306 }, + { 0x00104 , 0x00041 , 0x00328 }, + { 0x00105 , 0x00061 , 0x00328 }, + { 0x00106 , 0x00043 , 0x00301 }, + { 0x00107 , 0x00063 , 0x00301 }, + { 0x00108 , 0x00043 , 0x00302 }, + { 0x00109 , 0x00063 , 0x00302 }, + { 0x0010A , 0x00043 , 0x00307 }, + { 0x0010B , 0x00063 , 0x00307 }, + { 0x0010C , 0x00043 , 0x0030C }, + { 0x0010D , 0x00063 , 0x0030C }, + { 0x0010E , 0x00044 , 0x0030C }, + { 0x0010F , 0x00064 , 0x0030C }, + { 0x00112 , 0x00045 , 0x00304 }, + { 0x00113 , 0x00065 , 0x00304 }, + { 0x00114 , 0x00045 , 0x00306 }, + { 0x00115 , 0x00065 , 0x00306 }, + { 0x00116 , 0x00045 , 0x00307 }, + { 0x00117 , 0x00065 , 0x00307 }, + { 0x00118 , 0x00045 , 0x00328 }, + { 0x00119 , 0x00065 , 0x00328 }, + { 0x0011A , 0x00045 , 0x0030C }, + { 0x0011B , 0x00065 , 0x0030C }, + { 0x0011C , 0x00047 , 0x00302 }, + { 0x0011D , 0x00067 , 0x00302 }, + { 0x0011E , 0x00047 , 0x00306 }, + { 0x0011F , 0x00067 , 0x00306 }, + { 0x00120 , 0x00047 , 0x00307 }, + { 0x00121 , 0x00067 , 0x00307 }, + { 0x00122 , 0x00047 , 0x00327 }, + { 0x00123 , 0x00067 , 0x00327 }, + { 0x00124 , 0x00048 , 0x00302 }, + { 0x00125 , 0x00068 , 0x00302 }, + { 0x00128 , 0x00049 , 0x00303 }, + { 0x00129 , 0x00069 , 0x00303 }, + { 0x0012A , 0x00049 , 0x00304 }, + { 0x0012B , 0x00069 , 0x00304 }, + { 0x0012C , 0x00049 , 0x00306 }, + { 0x0012D , 0x00069 , 0x00306 }, + { 0x0012E , 0x00049 , 0x00328 }, + { 0x0012F , 0x00069 , 0x00328 }, + { 0x00130 , 0x00049 , 0x00307 }, + { 0x00134 , 0x0004A , 0x00302 }, + { 0x00135 , 0x0006A , 0x00302 }, + { 0x00136 , 0x0004B , 0x00327 }, + { 0x00137 , 0x0006B , 0x00327 }, + { 0x00139 , 0x0004C , 0x00301 }, + { 0x0013A , 0x0006C , 0x00301 }, + { 0x0013B , 0x0004C , 0x00327 }, + { 0x0013C , 0x0006C , 0x00327 }, + { 0x0013D , 0x0004C , 0x0030C }, + { 0x0013E , 0x0006C , 0x0030C }, + { 0x00143 , 0x0004E , 0x00301 }, + { 0x00144 , 0x0006E , 0x00301 }, + { 0x00145 , 0x0004E , 0x00327 }, + { 0x00146 , 0x0006E , 0x00327 }, + { 0x00147 , 0x0004E , 0x0030C }, + { 0x00148 , 0x0006E , 0x0030C }, + { 0x0014C , 0x0004F , 0x00304 }, + { 0x0014D , 0x0006F , 0x00304 }, + { 0x0014E , 0x0004F , 0x00306 }, + { 0x0014F , 0x0006F , 0x00306 }, + { 0x00150 , 0x0004F , 0x0030B }, + { 0x00151 , 0x0006F , 0x0030B }, + { 0x00154 , 0x00052 , 0x00301 }, + { 0x00155 , 0x00072 , 0x00301 }, + { 0x00156 , 0x00052 , 0x00327 }, + { 0x00157 , 0x00072 , 0x00327 }, + { 0x00158 , 0x00052 , 0x0030C }, + { 0x00159 , 0x00072 , 0x0030C }, + { 0x0015A , 0x00053 , 0x00301 }, + { 0x0015B , 0x00073 , 0x00301 }, + { 0x0015C , 0x00053 , 0x00302 }, + { 0x0015D , 0x00073 , 0x00302 }, + { 0x0015E , 0x00053 , 0x00327 }, + { 0x0015F , 0x00073 , 0x00327 }, + { 0x00160 , 0x00053 , 0x0030C }, + { 0x00161 , 0x00073 , 0x0030C }, + { 0x00162 , 0x00054 , 0x00327 }, + { 0x00163 , 0x00074 , 0x00327 }, + { 0x00164 , 0x00054 , 0x0030C }, + { 0x00165 , 0x00074 , 0x0030C }, + { 0x00168 , 0x00055 , 0x00303 }, + { 0x00169 , 0x00075 , 0x00303 }, + { 0x0016A , 0x00055 , 0x00304 }, + { 0x0016B , 0x00075 , 0x00304 }, + { 0x0016C , 0x00055 , 0x00306 }, + { 0x0016D , 0x00075 , 0x00306 }, + { 0x0016E , 0x00055 , 0x0030A }, + { 0x0016F , 0x00075 , 0x0030A }, + { 0x00170 , 0x00055 , 0x0030B }, + { 0x00171 , 0x00075 , 0x0030B }, + { 0x00172 , 0x00055 , 0x00328 }, + { 0x00173 , 0x00075 , 0x00328 }, + { 0x00174 , 0x00057 , 0x00302 }, + { 0x00175 , 0x00077 , 0x00302 }, + { 0x00176 , 0x00059 , 0x00302 }, + { 0x00177 , 0x00079 , 0x00302 }, + { 0x00178 , 0x00059 , 0x00308 }, + { 0x00179 , 0x0005A , 0x00301 }, + { 0x0017A , 0x0007A , 0x00301 }, + { 0x0017B , 0x0005A , 0x00307 }, + { 0x0017C , 0x0007A , 0x00307 }, + { 0x0017D , 0x0005A , 0x0030C }, + { 0x0017E , 0x0007A , 0x0030C }, + { 0x001A0 , 0x0004F , 0x0031B }, + { 0x001A1 , 0x0006F , 0x0031B }, + { 0x001AF , 0x00055 , 0x0031B }, + { 0x001B0 , 0x00075 , 0x0031B }, + { 0x001CD , 0x00041 , 0x0030C }, + { 0x001CE , 0x00061 , 0x0030C }, + { 0x001CF , 0x00049 , 0x0030C }, + { 0x001D0 , 0x00069 , 0x0030C }, + { 0x001D1 , 0x0004F , 0x0030C }, + { 0x001D2 , 0x0006F , 0x0030C }, + { 0x001D3 , 0x00055 , 0x0030C }, + { 0x001D4 , 0x00075 , 0x0030C }, + { 0x001D5 , 0x000DC , 0x00304 }, + { 0x001D6 , 0x000FC , 0x00304 }, + { 0x001D7 , 0x000DC , 0x00301 }, + { 0x001D8 , 0x000FC , 0x00301 }, + { 0x001D9 , 0x000DC , 0x0030C }, + { 0x001DA , 0x000FC , 0x0030C }, + { 0x001DB , 0x000DC , 0x00300 }, + { 0x001DC , 0x000FC , 0x00300 }, + { 0x001DE , 0x000C4 , 0x00304 }, + { 0x001DF , 0x000E4 , 0x00304 }, + { 0x001E0 , 0x00226 , 0x00304 }, + { 0x001E1 , 0x00227 , 0x00304 }, + { 0x001E2 , 0x000C6 , 0x00304 }, + { 0x001E3 , 0x000E6 , 0x00304 }, + { 0x001E6 , 0x00047 , 0x0030C }, + { 0x001E7 , 0x00067 , 0x0030C }, + { 0x001E8 , 0x0004B , 0x0030C }, + { 0x001E9 , 0x0006B , 0x0030C }, + { 0x001EA , 0x0004F , 0x00328 }, + { 0x001EB , 0x0006F , 0x00328 }, + { 0x001EC , 0x001EA , 0x00304 }, + { 0x001ED , 0x001EB , 0x00304 }, + { 0x001EE , 0x001B7 , 0x0030C }, + { 0x001EF , 0x00292 , 0x0030C }, + { 0x001F0 , 0x0006A , 0x0030C }, + { 0x001F4 , 0x00047 , 0x00301 }, + { 0x001F5 , 0x00067 , 0x00301 }, + { 0x001F8 , 0x0004E , 0x00300 }, + { 0x001F9 , 0x0006E , 0x00300 }, + { 0x001FA , 0x000C5 , 0x00301 }, + { 0x001FB , 0x000E5 , 0x00301 }, + { 0x001FC , 0x000C6 , 0x00301 }, + { 0x001FD , 0x000E6 , 0x00301 }, + { 0x001FE , 0x000D8 , 0x00301 }, + { 0x001FF , 0x000F8 , 0x00301 }, + { 0x00200 , 0x00041 , 0x0030F }, + { 0x00201 , 0x00061 , 0x0030F }, + { 0x00202 , 0x00041 , 0x00311 }, + { 0x00203 , 0x00061 , 0x00311 }, + { 0x00204 , 0x00045 , 0x0030F }, + { 0x00205 , 0x00065 , 0x0030F }, + { 0x00206 , 0x00045 , 0x00311 }, + { 0x00207 , 0x00065 , 0x00311 }, + { 0x00208 , 0x00049 , 0x0030F }, + { 0x00209 , 0x00069 , 0x0030F }, + { 0x0020A , 0x00049 , 0x00311 }, + { 0x0020B , 0x00069 , 0x00311 }, + { 0x0020C , 0x0004F , 0x0030F }, + { 0x0020D , 0x0006F , 0x0030F }, + { 0x0020E , 0x0004F , 0x00311 }, + { 0x0020F , 0x0006F , 0x00311 }, + { 0x00210 , 0x00052 , 0x0030F }, + { 0x00211 , 0x00072 , 0x0030F }, + { 0x00212 , 0x00052 , 0x00311 }, + { 0x00213 , 0x00072 , 0x00311 }, + { 0x00214 , 0x00055 , 0x0030F }, + { 0x00215 , 0x00075 , 0x0030F }, + { 0x00216 , 0x00055 , 0x00311 }, + { 0x00217 , 0x00075 , 0x00311 }, + { 0x00218 , 0x00053 , 0x00326 }, + { 0x00219 , 0x00073 , 0x00326 }, + { 0x0021A , 0x00054 , 0x00326 }, + { 0x0021B , 0x00074 , 0x00326 }, + { 0x0021E , 0x00048 , 0x0030C }, + { 0x0021F , 0x00068 , 0x0030C }, + { 0x00226 , 0x00041 , 0x00307 }, + { 0x00227 , 0x00061 , 0x00307 }, + { 0x00228 , 0x00045 , 0x00327 }, + { 0x00229 , 0x00065 , 0x00327 }, + { 0x0022A , 0x000D6 , 0x00304 }, + { 0x0022B , 0x000F6 , 0x00304 }, + { 0x0022C , 0x000D5 , 0x00304 }, + { 0x0022D , 0x000F5 , 0x00304 }, + { 0x0022E , 0x0004F , 0x00307 }, + { 0x0022F , 0x0006F , 0x00307 }, + { 0x00230 , 0x0022E , 0x00304 }, + { 0x00231 , 0x0022F , 0x00304 }, + { 0x00232 , 0x00059 , 0x00304 }, + { 0x00233 , 0x00079 , 0x00304 }, + { 0x00385 , 0x000A8 , 0x00301 }, + { 0x00386 , 0x00391 , 0x00301 }, + { 0x00388 , 0x00395 , 0x00301 }, + { 0x00389 , 0x00397 , 0x00301 }, + { 0x0038A , 0x00399 , 0x00301 }, + { 0x0038C , 0x0039F , 0x00301 }, + { 0x0038E , 0x003A5 , 0x00301 }, + { 0x0038F , 0x003A9 , 0x00301 }, + { 0x00390 , 0x003CA , 0x00301 }, + { 0x003AA , 0x00399 , 0x00308 }, + { 0x003AB , 0x003A5 , 0x00308 }, + { 0x003AC , 0x003B1 , 0x00301 }, + { 0x003AD , 0x003B5 , 0x00301 }, + { 0x003AE , 0x003B7 , 0x00301 }, + { 0x003AF , 0x003B9 , 0x00301 }, + { 0x003B0 , 0x003CB , 0x00301 }, + { 0x003CA , 0x003B9 , 0x00308 }, + { 0x003CB , 0x003C5 , 0x00308 }, + { 0x003CC , 0x003BF , 0x00301 }, + { 0x003CD , 0x003C5 , 0x00301 }, + { 0x003CE , 0x003C9 , 0x00301 }, + { 0x003D3 , 0x003D2 , 0x00301 }, + { 0x003D4 , 0x003D2 , 0x00308 }, + { 0x00400 , 0x00415 , 0x00300 }, + { 0x00401 , 0x00415 , 0x00308 }, + { 0x00403 , 0x00413 , 0x00301 }, + { 0x00407 , 0x00406 , 0x00308 }, + { 0x0040C , 0x0041A , 0x00301 }, + { 0x0040D , 0x00418 , 0x00300 }, + { 0x0040E , 0x00423 , 0x00306 }, + { 0x00419 , 0x00418 , 0x00306 }, + { 0x00439 , 0x00438 , 0x00306 }, + { 0x00450 , 0x00435 , 0x00300 }, + { 0x00451 , 0x00435 , 0x00308 }, + { 0x00453 , 0x00433 , 0x00301 }, + { 0x00457 , 0x00456 , 0x00308 }, + { 0x0045C , 0x0043A , 0x00301 }, + { 0x0045D , 0x00438 , 0x00300 }, + { 0x0045E , 0x00443 , 0x00306 }, + { 0x00476 , 0x00474 , 0x0030F }, + { 0x00477 , 0x00475 , 0x0030F }, + { 0x004C1 , 0x00416 , 0x00306 }, + { 0x004C2 , 0x00436 , 0x00306 }, + { 0x004D0 , 0x00410 , 0x00306 }, + { 0x004D1 , 0x00430 , 0x00306 }, + { 0x004D2 , 0x00410 , 0x00308 }, + { 0x004D3 , 0x00430 , 0x00308 }, + { 0x004D6 , 0x00415 , 0x00306 }, + { 0x004D7 , 0x00435 , 0x00306 }, + { 0x004DA , 0x004D8 , 0x00308 }, + { 0x004DB , 0x004D9 , 0x00308 }, + { 0x004DC , 0x00416 , 0x00308 }, + { 0x004DD , 0x00436 , 0x00308 }, + { 0x004DE , 0x00417 , 0x00308 }, + { 0x004DF , 0x00437 , 0x00308 }, + { 0x004E2 , 0x00418 , 0x00304 }, + { 0x004E3 , 0x00438 , 0x00304 }, + { 0x004E4 , 0x00418 , 0x00308 }, + { 0x004E5 , 0x00438 , 0x00308 }, + { 0x004E6 , 0x0041E , 0x00308 }, + { 0x004E7 , 0x0043E , 0x00308 }, + { 0x004EA , 0x004E8 , 0x00308 }, + { 0x004EB , 0x004E9 , 0x00308 }, + { 0x004EC , 0x0042D , 0x00308 }, + { 0x004ED , 0x0044D , 0x00308 }, + { 0x004EE , 0x00423 , 0x00304 }, + { 0x004EF , 0x00443 , 0x00304 }, + { 0x004F0 , 0x00423 , 0x00308 }, + { 0x004F1 , 0x00443 , 0x00308 }, + { 0x004F2 , 0x00423 , 0x0030B }, + { 0x004F3 , 0x00443 , 0x0030B }, + { 0x004F4 , 0x00427 , 0x00308 }, + { 0x004F5 , 0x00447 , 0x00308 }, + { 0x004F8 , 0x0042B , 0x00308 }, + { 0x004F9 , 0x0044B , 0x00308 }, + { 0x00622 , 0x00627 , 0x00653 }, + { 0x00623 , 0x00627 , 0x00654 }, + { 0x00624 , 0x00648 , 0x00654 }, + { 0x00625 , 0x00627 , 0x00655 }, + { 0x00626 , 0x0064A , 0x00654 }, + { 0x006C0 , 0x006D5 , 0x00654 }, + { 0x006C2 , 0x006C1 , 0x00654 }, + { 0x006D3 , 0x006D2 , 0x00654 }, + { 0x00929 , 0x00928 , 0x0093C }, + { 0x00931 , 0x00930 , 0x0093C }, + { 0x00934 , 0x00933 , 0x0093C }, + { 0x009CB , 0x009C7 , 0x009BE }, + { 0x009CC , 0x009C7 , 0x009D7 }, + { 0x00B48 , 0x00B47 , 0x00B56 }, + { 0x00B4B , 0x00B47 , 0x00B3E }, + { 0x00B4C , 0x00B47 , 0x00B57 }, + { 0x00B94 , 0x00B92 , 0x00BD7 }, + { 0x00BCA , 0x00BC6 , 0x00BBE }, + { 0x00BCB , 0x00BC7 , 0x00BBE }, + { 0x00BCC , 0x00BC6 , 0x00BD7 }, + { 0x00C48 , 0x00C46 , 0x00C56 }, + { 0x00CC0 , 0x00CBF , 0x00CD5 }, + { 0x00CC7 , 0x00CC6 , 0x00CD5 }, + { 0x00CC8 , 0x00CC6 , 0x00CD6 }, + { 0x00CCA , 0x00CC6 , 0x00CC2 }, + { 0x00CCB , 0x00CCA , 0x00CD5 }, + { 0x00D4A , 0x00D46 , 0x00D3E }, + { 0x00D4B , 0x00D47 , 0x00D3E }, + { 0x00D4C , 0x00D46 , 0x00D57 }, + { 0x00DDA , 0x00DD9 , 0x00DCA }, + { 0x00DDC , 0x00DD9 , 0x00DCF }, + { 0x00DDD , 0x00DDC , 0x00DCA }, + { 0x00DDE , 0x00DD9 , 0x00DDF }, + { 0x01026 , 0x01025 , 0x0102E }, + { 0x01B06 , 0x01B05 , 0x01B35 }, + { 0x01B08 , 0x01B07 , 0x01B35 }, + { 0x01B0A , 0x01B09 , 0x01B35 }, + { 0x01B0C , 0x01B0B , 0x01B35 }, + { 0x01B0E , 0x01B0D , 0x01B35 }, + { 0x01B12 , 0x01B11 , 0x01B35 }, + { 0x01B3B , 0x01B3A , 0x01B35 }, + { 0x01B3D , 0x01B3C , 0x01B35 }, + { 0x01B40 , 0x01B3E , 0x01B35 }, + { 0x01B41 , 0x01B3F , 0x01B35 }, + { 0x01B43 , 0x01B42 , 0x01B35 }, + { 0x01E00 , 0x00041 , 0x00325 }, + { 0x01E01 , 0x00061 , 0x00325 }, + { 0x01E02 , 0x00042 , 0x00307 }, + { 0x01E03 , 0x00062 , 0x00307 }, + { 0x01E04 , 0x00042 , 0x00323 }, + { 0x01E05 , 0x00062 , 0x00323 }, + { 0x01E06 , 0x00042 , 0x00331 }, + { 0x01E07 , 0x00062 , 0x00331 }, + { 0x01E08 , 0x000C7 , 0x00301 }, + { 0x01E09 , 0x000E7 , 0x00301 }, + { 0x01E0A , 0x00044 , 0x00307 }, + { 0x01E0B , 0x00064 , 0x00307 }, + { 0x01E0C , 0x00044 , 0x00323 }, + { 0x01E0D , 0x00064 , 0x00323 }, + { 0x01E0E , 0x00044 , 0x00331 }, + { 0x01E0F , 0x00064 , 0x00331 }, + { 0x01E10 , 0x00044 , 0x00327 }, + { 0x01E11 , 0x00064 , 0x00327 }, + { 0x01E12 , 0x00044 , 0x0032D }, + { 0x01E13 , 0x00064 , 0x0032D }, + { 0x01E14 , 0x00112 , 0x00300 }, + { 0x01E15 , 0x00113 , 0x00300 }, + { 0x01E16 , 0x00112 , 0x00301 }, + { 0x01E17 , 0x00113 , 0x00301 }, + { 0x01E18 , 0x00045 , 0x0032D }, + { 0x01E19 , 0x00065 , 0x0032D }, + { 0x01E1A , 0x00045 , 0x00330 }, + { 0x01E1B , 0x00065 , 0x00330 }, + { 0x01E1C , 0x00228 , 0x00306 }, + { 0x01E1D , 0x00229 , 0x00306 }, + { 0x01E1E , 0x00046 , 0x00307 }, + { 0x01E1F , 0x00066 , 0x00307 }, + { 0x01E20 , 0x00047 , 0x00304 }, + { 0x01E21 , 0x00067 , 0x00304 }, + { 0x01E22 , 0x00048 , 0x00307 }, + { 0x01E23 , 0x00068 , 0x00307 }, + { 0x01E24 , 0x00048 , 0x00323 }, + { 0x01E25 , 0x00068 , 0x00323 }, + { 0x01E26 , 0x00048 , 0x00308 }, + { 0x01E27 , 0x00068 , 0x00308 }, + { 0x01E28 , 0x00048 , 0x00327 }, + { 0x01E29 , 0x00068 , 0x00327 }, + { 0x01E2A , 0x00048 , 0x0032E }, + { 0x01E2B , 0x00068 , 0x0032E }, + { 0x01E2C , 0x00049 , 0x00330 }, + { 0x01E2D , 0x00069 , 0x00330 }, + { 0x01E2E , 0x000CF , 0x00301 }, + { 0x01E2F , 0x000EF , 0x00301 }, + { 0x01E30 , 0x0004B , 0x00301 }, + { 0x01E31 , 0x0006B , 0x00301 }, + { 0x01E32 , 0x0004B , 0x00323 }, + { 0x01E33 , 0x0006B , 0x00323 }, + { 0x01E34 , 0x0004B , 0x00331 }, + { 0x01E35 , 0x0006B , 0x00331 }, + { 0x01E36 , 0x0004C , 0x00323 }, + { 0x01E37 , 0x0006C , 0x00323 }, + { 0x01E38 , 0x01E36 , 0x00304 }, + { 0x01E39 , 0x01E37 , 0x00304 }, + { 0x01E3A , 0x0004C , 0x00331 }, + { 0x01E3B , 0x0006C , 0x00331 }, + { 0x01E3C , 0x0004C , 0x0032D }, + { 0x01E3D , 0x0006C , 0x0032D }, + { 0x01E3E , 0x0004D , 0x00301 }, + { 0x01E3F , 0x0006D , 0x00301 }, + { 0x01E40 , 0x0004D , 0x00307 }, + { 0x01E41 , 0x0006D , 0x00307 }, + { 0x01E42 , 0x0004D , 0x00323 }, + { 0x01E43 , 0x0006D , 0x00323 }, + { 0x01E44 , 0x0004E , 0x00307 }, + { 0x01E45 , 0x0006E , 0x00307 }, + { 0x01E46 , 0x0004E , 0x00323 }, + { 0x01E47 , 0x0006E , 0x00323 }, + { 0x01E48 , 0x0004E , 0x00331 }, + { 0x01E49 , 0x0006E , 0x00331 }, + { 0x01E4A , 0x0004E , 0x0032D }, + { 0x01E4B , 0x0006E , 0x0032D }, + { 0x01E4C , 0x000D5 , 0x00301 }, + { 0x01E4D , 0x000F5 , 0x00301 }, + { 0x01E4E , 0x000D5 , 0x00308 }, + { 0x01E4F , 0x000F5 , 0x00308 }, + { 0x01E50 , 0x0014C , 0x00300 }, + { 0x01E51 , 0x0014D , 0x00300 }, + { 0x01E52 , 0x0014C , 0x00301 }, + { 0x01E53 , 0x0014D , 0x00301 }, + { 0x01E54 , 0x00050 , 0x00301 }, + { 0x01E55 , 0x00070 , 0x00301 }, + { 0x01E56 , 0x00050 , 0x00307 }, + { 0x01E57 , 0x00070 , 0x00307 }, + { 0x01E58 , 0x00052 , 0x00307 }, + { 0x01E59 , 0x00072 , 0x00307 }, + { 0x01E5A , 0x00052 , 0x00323 }, + { 0x01E5B , 0x00072 , 0x00323 }, + { 0x01E5C , 0x01E5A , 0x00304 }, + { 0x01E5D , 0x01E5B , 0x00304 }, + { 0x01E5E , 0x00052 , 0x00331 }, + { 0x01E5F , 0x00072 , 0x00331 }, + { 0x01E60 , 0x00053 , 0x00307 }, + { 0x01E61 , 0x00073 , 0x00307 }, + { 0x01E62 , 0x00053 , 0x00323 }, + { 0x01E63 , 0x00073 , 0x00323 }, + { 0x01E64 , 0x0015A , 0x00307 }, + { 0x01E65 , 0x0015B , 0x00307 }, + { 0x01E66 , 0x00160 , 0x00307 }, + { 0x01E67 , 0x00161 , 0x00307 }, + { 0x01E68 , 0x01E62 , 0x00307 }, + { 0x01E69 , 0x01E63 , 0x00307 }, + { 0x01E6A , 0x00054 , 0x00307 }, + { 0x01E6B , 0x00074 , 0x00307 }, + { 0x01E6C , 0x00054 , 0x00323 }, + { 0x01E6D , 0x00074 , 0x00323 }, + { 0x01E6E , 0x00054 , 0x00331 }, + { 0x01E6F , 0x00074 , 0x00331 }, + { 0x01E70 , 0x00054 , 0x0032D }, + { 0x01E71 , 0x00074 , 0x0032D }, + { 0x01E72 , 0x00055 , 0x00324 }, + { 0x01E73 , 0x00075 , 0x00324 }, + { 0x01E74 , 0x00055 , 0x00330 }, + { 0x01E75 , 0x00075 , 0x00330 }, + { 0x01E76 , 0x00055 , 0x0032D }, + { 0x01E77 , 0x00075 , 0x0032D }, + { 0x01E78 , 0x00168 , 0x00301 }, + { 0x01E79 , 0x00169 , 0x00301 }, + { 0x01E7A , 0x0016A , 0x00308 }, + { 0x01E7B , 0x0016B , 0x00308 }, + { 0x01E7C , 0x00056 , 0x00303 }, + { 0x01E7D , 0x00076 , 0x00303 }, + { 0x01E7E , 0x00056 , 0x00323 }, + { 0x01E7F , 0x00076 , 0x00323 }, + { 0x01E80 , 0x00057 , 0x00300 }, + { 0x01E81 , 0x00077 , 0x00300 }, + { 0x01E82 , 0x00057 , 0x00301 }, + { 0x01E83 , 0x00077 , 0x00301 }, + { 0x01E84 , 0x00057 , 0x00308 }, + { 0x01E85 , 0x00077 , 0x00308 }, + { 0x01E86 , 0x00057 , 0x00307 }, + { 0x01E87 , 0x00077 , 0x00307 }, + { 0x01E88 , 0x00057 , 0x00323 }, + { 0x01E89 , 0x00077 , 0x00323 }, + { 0x01E8A , 0x00058 , 0x00307 }, + { 0x01E8B , 0x00078 , 0x00307 }, + { 0x01E8C , 0x00058 , 0x00308 }, + { 0x01E8D , 0x00078 , 0x00308 }, + { 0x01E8E , 0x00059 , 0x00307 }, + { 0x01E8F , 0x00079 , 0x00307 }, + { 0x01E90 , 0x0005A , 0x00302 }, + { 0x01E91 , 0x0007A , 0x00302 }, + { 0x01E92 , 0x0005A , 0x00323 }, + { 0x01E93 , 0x0007A , 0x00323 }, + { 0x01E94 , 0x0005A , 0x00331 }, + { 0x01E95 , 0x0007A , 0x00331 }, + { 0x01E96 , 0x00068 , 0x00331 }, + { 0x01E97 , 0x00074 , 0x00308 }, + { 0x01E98 , 0x00077 , 0x0030A }, + { 0x01E99 , 0x00079 , 0x0030A }, + { 0x01E9B , 0x0017F , 0x00307 }, + { 0x01EA0 , 0x00041 , 0x00323 }, + { 0x01EA1 , 0x00061 , 0x00323 }, + { 0x01EA2 , 0x00041 , 0x00309 }, + { 0x01EA3 , 0x00061 , 0x00309 }, + { 0x01EA4 , 0x000C2 , 0x00301 }, + { 0x01EA5 , 0x000E2 , 0x00301 }, + { 0x01EA6 , 0x000C2 , 0x00300 }, + { 0x01EA7 , 0x000E2 , 0x00300 }, + { 0x01EA8 , 0x000C2 , 0x00309 }, + { 0x01EA9 , 0x000E2 , 0x00309 }, + { 0x01EAA , 0x000C2 , 0x00303 }, + { 0x01EAB , 0x000E2 , 0x00303 }, + { 0x01EAC , 0x01EA0 , 0x00302 }, + { 0x01EAD , 0x01EA1 , 0x00302 }, + { 0x01EAE , 0x00102 , 0x00301 }, + { 0x01EAF , 0x00103 , 0x00301 }, + { 0x01EB0 , 0x00102 , 0x00300 }, + { 0x01EB1 , 0x00103 , 0x00300 }, + { 0x01EB2 , 0x00102 , 0x00309 }, + { 0x01EB3 , 0x00103 , 0x00309 }, + { 0x01EB4 , 0x00102 , 0x00303 }, + { 0x01EB5 , 0x00103 , 0x00303 }, + { 0x01EB6 , 0x01EA0 , 0x00306 }, + { 0x01EB7 , 0x01EA1 , 0x00306 }, + { 0x01EB8 , 0x00045 , 0x00323 }, + { 0x01EB9 , 0x00065 , 0x00323 }, + { 0x01EBA , 0x00045 , 0x00309 }, + { 0x01EBB , 0x00065 , 0x00309 }, + { 0x01EBC , 0x00045 , 0x00303 }, + { 0x01EBD , 0x00065 , 0x00303 }, + { 0x01EBE , 0x000CA , 0x00301 }, + { 0x01EBF , 0x000EA , 0x00301 }, + { 0x01EC0 , 0x000CA , 0x00300 }, + { 0x01EC1 , 0x000EA , 0x00300 }, + { 0x01EC2 , 0x000CA , 0x00309 }, + { 0x01EC3 , 0x000EA , 0x00309 }, + { 0x01EC4 , 0x000CA , 0x00303 }, + { 0x01EC5 , 0x000EA , 0x00303 }, + { 0x01EC6 , 0x01EB8 , 0x00302 }, + { 0x01EC7 , 0x01EB9 , 0x00302 }, + { 0x01EC8 , 0x00049 , 0x00309 }, + { 0x01EC9 , 0x00069 , 0x00309 }, + { 0x01ECA , 0x00049 , 0x00323 }, + { 0x01ECB , 0x00069 , 0x00323 }, + { 0x01ECC , 0x0004F , 0x00323 }, + { 0x01ECD , 0x0006F , 0x00323 }, + { 0x01ECE , 0x0004F , 0x00309 }, + { 0x01ECF , 0x0006F , 0x00309 }, + { 0x01ED0 , 0x000D4 , 0x00301 }, + { 0x01ED1 , 0x000F4 , 0x00301 }, + { 0x01ED2 , 0x000D4 , 0x00300 }, + { 0x01ED3 , 0x000F4 , 0x00300 }, + { 0x01ED4 , 0x000D4 , 0x00309 }, + { 0x01ED5 , 0x000F4 , 0x00309 }, + { 0x01ED6 , 0x000D4 , 0x00303 }, + { 0x01ED7 , 0x000F4 , 0x00303 }, + { 0x01ED8 , 0x01ECC , 0x00302 }, + { 0x01ED9 , 0x01ECD , 0x00302 }, + { 0x01EDA , 0x001A0 , 0x00301 }, + { 0x01EDB , 0x001A1 , 0x00301 }, + { 0x01EDC , 0x001A0 , 0x00300 }, + { 0x01EDD , 0x001A1 , 0x00300 }, + { 0x01EDE , 0x001A0 , 0x00309 }, + { 0x01EDF , 0x001A1 , 0x00309 }, + { 0x01EE0 , 0x001A0 , 0x00303 }, + { 0x01EE1 , 0x001A1 , 0x00303 }, + { 0x01EE2 , 0x001A0 , 0x00323 }, + { 0x01EE3 , 0x001A1 , 0x00323 }, + { 0x01EE4 , 0x00055 , 0x00323 }, + { 0x01EE5 , 0x00075 , 0x00323 }, + { 0x01EE6 , 0x00055 , 0x00309 }, + { 0x01EE7 , 0x00075 , 0x00309 }, + { 0x01EE8 , 0x001AF , 0x00301 }, + { 0x01EE9 , 0x001B0 , 0x00301 }, + { 0x01EEA , 0x001AF , 0x00300 }, + { 0x01EEB , 0x001B0 , 0x00300 }, + { 0x01EEC , 0x001AF , 0x00309 }, + { 0x01EED , 0x001B0 , 0x00309 }, + { 0x01EEE , 0x001AF , 0x00303 }, + { 0x01EEF , 0x001B0 , 0x00303 }, + { 0x01EF0 , 0x001AF , 0x00323 }, + { 0x01EF1 , 0x001B0 , 0x00323 }, + { 0x01EF2 , 0x00059 , 0x00300 }, + { 0x01EF3 , 0x00079 , 0x00300 }, + { 0x01EF4 , 0x00059 , 0x00323 }, + { 0x01EF5 , 0x00079 , 0x00323 }, + { 0x01EF6 , 0x00059 , 0x00309 }, + { 0x01EF7 , 0x00079 , 0x00309 }, + { 0x01EF8 , 0x00059 , 0x00303 }, + { 0x01EF9 , 0x00079 , 0x00303 }, + { 0x01F00 , 0x003B1 , 0x00313 }, + { 0x01F01 , 0x003B1 , 0x00314 }, + { 0x01F02 , 0x01F00 , 0x00300 }, + { 0x01F03 , 0x01F01 , 0x00300 }, + { 0x01F04 , 0x01F00 , 0x00301 }, + { 0x01F05 , 0x01F01 , 0x00301 }, + { 0x01F06 , 0x01F00 , 0x00342 }, + { 0x01F07 , 0x01F01 , 0x00342 }, + { 0x01F08 , 0x00391 , 0x00313 }, + { 0x01F09 , 0x00391 , 0x00314 }, + { 0x01F0A , 0x01F08 , 0x00300 }, + { 0x01F0B , 0x01F09 , 0x00300 }, + { 0x01F0C , 0x01F08 , 0x00301 }, + { 0x01F0D , 0x01F09 , 0x00301 }, + { 0x01F0E , 0x01F08 , 0x00342 }, + { 0x01F0F , 0x01F09 , 0x00342 }, + { 0x01F10 , 0x003B5 , 0x00313 }, + { 0x01F11 , 0x003B5 , 0x00314 }, + { 0x01F12 , 0x01F10 , 0x00300 }, + { 0x01F13 , 0x01F11 , 0x00300 }, + { 0x01F14 , 0x01F10 , 0x00301 }, + { 0x01F15 , 0x01F11 , 0x00301 }, + { 0x01F18 , 0x00395 , 0x00313 }, + { 0x01F19 , 0x00395 , 0x00314 }, + { 0x01F1A , 0x01F18 , 0x00300 }, + { 0x01F1B , 0x01F19 , 0x00300 }, + { 0x01F1C , 0x01F18 , 0x00301 }, + { 0x01F1D , 0x01F19 , 0x00301 }, + { 0x01F20 , 0x003B7 , 0x00313 }, + { 0x01F21 , 0x003B7 , 0x00314 }, + { 0x01F22 , 0x01F20 , 0x00300 }, + { 0x01F23 , 0x01F21 , 0x00300 }, + { 0x01F24 , 0x01F20 , 0x00301 }, + { 0x01F25 , 0x01F21 , 0x00301 }, + { 0x01F26 , 0x01F20 , 0x00342 }, + { 0x01F27 , 0x01F21 , 0x00342 }, + { 0x01F28 , 0x00397 , 0x00313 }, + { 0x01F29 , 0x00397 , 0x00314 }, + { 0x01F2A , 0x01F28 , 0x00300 }, + { 0x01F2B , 0x01F29 , 0x00300 }, + { 0x01F2C , 0x01F28 , 0x00301 }, + { 0x01F2D , 0x01F29 , 0x00301 }, + { 0x01F2E , 0x01F28 , 0x00342 }, + { 0x01F2F , 0x01F29 , 0x00342 }, + { 0x01F30 , 0x003B9 , 0x00313 }, + { 0x01F31 , 0x003B9 , 0x00314 }, + { 0x01F32 , 0x01F30 , 0x00300 }, + { 0x01F33 , 0x01F31 , 0x00300 }, + { 0x01F34 , 0x01F30 , 0x00301 }, + { 0x01F35 , 0x01F31 , 0x00301 }, + { 0x01F36 , 0x01F30 , 0x00342 }, + { 0x01F37 , 0x01F31 , 0x00342 }, + { 0x01F38 , 0x00399 , 0x00313 }, + { 0x01F39 , 0x00399 , 0x00314 }, + { 0x01F3A , 0x01F38 , 0x00300 }, + { 0x01F3B , 0x01F39 , 0x00300 }, + { 0x01F3C , 0x01F38 , 0x00301 }, + { 0x01F3D , 0x01F39 , 0x00301 }, + { 0x01F3E , 0x01F38 , 0x00342 }, + { 0x01F3F , 0x01F39 , 0x00342 }, + { 0x01F40 , 0x003BF , 0x00313 }, + { 0x01F41 , 0x003BF , 0x00314 }, + { 0x01F42 , 0x01F40 , 0x00300 }, + { 0x01F43 , 0x01F41 , 0x00300 }, + { 0x01F44 , 0x01F40 , 0x00301 }, + { 0x01F45 , 0x01F41 , 0x00301 }, + { 0x01F48 , 0x0039F , 0x00313 }, + { 0x01F49 , 0x0039F , 0x00314 }, + { 0x01F4A , 0x01F48 , 0x00300 }, + { 0x01F4B , 0x01F49 , 0x00300 }, + { 0x01F4C , 0x01F48 , 0x00301 }, + { 0x01F4D , 0x01F49 , 0x00301 }, + { 0x01F50 , 0x003C5 , 0x00313 }, + { 0x01F51 , 0x003C5 , 0x00314 }, + { 0x01F52 , 0x01F50 , 0x00300 }, + { 0x01F53 , 0x01F51 , 0x00300 }, + { 0x01F54 , 0x01F50 , 0x00301 }, + { 0x01F55 , 0x01F51 , 0x00301 }, + { 0x01F56 , 0x01F50 , 0x00342 }, + { 0x01F57 , 0x01F51 , 0x00342 }, + { 0x01F59 , 0x003A5 , 0x00314 }, + { 0x01F5B , 0x01F59 , 0x00300 }, + { 0x01F5D , 0x01F59 , 0x00301 }, + { 0x01F5F , 0x01F59 , 0x00342 }, + { 0x01F60 , 0x003C9 , 0x00313 }, + { 0x01F61 , 0x003C9 , 0x00314 }, + { 0x01F62 , 0x01F60 , 0x00300 }, + { 0x01F63 , 0x01F61 , 0x00300 }, + { 0x01F64 , 0x01F60 , 0x00301 }, + { 0x01F65 , 0x01F61 , 0x00301 }, + { 0x01F66 , 0x01F60 , 0x00342 }, + { 0x01F67 , 0x01F61 , 0x00342 }, + { 0x01F68 , 0x003A9 , 0x00313 }, + { 0x01F69 , 0x003A9 , 0x00314 }, + { 0x01F6A , 0x01F68 , 0x00300 }, + { 0x01F6B , 0x01F69 , 0x00300 }, + { 0x01F6C , 0x01F68 , 0x00301 }, + { 0x01F6D , 0x01F69 , 0x00301 }, + { 0x01F6E , 0x01F68 , 0x00342 }, + { 0x01F6F , 0x01F69 , 0x00342 }, + { 0x01F70 , 0x003B1 , 0x00300 }, + { 0x01F72 , 0x003B5 , 0x00300 }, + { 0x01F74 , 0x003B7 , 0x00300 }, + { 0x01F76 , 0x003B9 , 0x00300 }, + { 0x01F78 , 0x003BF , 0x00300 }, + { 0x01F7A , 0x003C5 , 0x00300 }, + { 0x01F7C , 0x003C9 , 0x00300 }, + { 0x01F80 , 0x01F00 , 0x00345 }, + { 0x01F81 , 0x01F01 , 0x00345 }, + { 0x01F82 , 0x01F02 , 0x00345 }, + { 0x01F83 , 0x01F03 , 0x00345 }, + { 0x01F84 , 0x01F04 , 0x00345 }, + { 0x01F85 , 0x01F05 , 0x00345 }, + { 0x01F86 , 0x01F06 , 0x00345 }, + { 0x01F87 , 0x01F07 , 0x00345 }, + { 0x01F88 , 0x01F08 , 0x00345 }, + { 0x01F89 , 0x01F09 , 0x00345 }, + { 0x01F8A , 0x01F0A , 0x00345 }, + { 0x01F8B , 0x01F0B , 0x00345 }, + { 0x01F8C , 0x01F0C , 0x00345 }, + { 0x01F8D , 0x01F0D , 0x00345 }, + { 0x01F8E , 0x01F0E , 0x00345 }, + { 0x01F8F , 0x01F0F , 0x00345 }, + { 0x01F90 , 0x01F20 , 0x00345 }, + { 0x01F91 , 0x01F21 , 0x00345 }, + { 0x01F92 , 0x01F22 , 0x00345 }, + { 0x01F93 , 0x01F23 , 0x00345 }, + { 0x01F94 , 0x01F24 , 0x00345 }, + { 0x01F95 , 0x01F25 , 0x00345 }, + { 0x01F96 , 0x01F26 , 0x00345 }, + { 0x01F97 , 0x01F27 , 0x00345 }, + { 0x01F98 , 0x01F28 , 0x00345 }, + { 0x01F99 , 0x01F29 , 0x00345 }, + { 0x01F9A , 0x01F2A , 0x00345 }, + { 0x01F9B , 0x01F2B , 0x00345 }, + { 0x01F9C , 0x01F2C , 0x00345 }, + { 0x01F9D , 0x01F2D , 0x00345 }, + { 0x01F9E , 0x01F2E , 0x00345 }, + { 0x01F9F , 0x01F2F , 0x00345 }, + { 0x01FA0 , 0x01F60 , 0x00345 }, + { 0x01FA1 , 0x01F61 , 0x00345 }, + { 0x01FA2 , 0x01F62 , 0x00345 }, + { 0x01FA3 , 0x01F63 , 0x00345 }, + { 0x01FA4 , 0x01F64 , 0x00345 }, + { 0x01FA5 , 0x01F65 , 0x00345 }, + { 0x01FA6 , 0x01F66 , 0x00345 }, + { 0x01FA7 , 0x01F67 , 0x00345 }, + { 0x01FA8 , 0x01F68 , 0x00345 }, + { 0x01FA9 , 0x01F69 , 0x00345 }, + { 0x01FAA , 0x01F6A , 0x00345 }, + { 0x01FAB , 0x01F6B , 0x00345 }, + { 0x01FAC , 0x01F6C , 0x00345 }, + { 0x01FAD , 0x01F6D , 0x00345 }, + { 0x01FAE , 0x01F6E , 0x00345 }, + { 0x01FAF , 0x01F6F , 0x00345 }, + { 0x01FB0 , 0x003B1 , 0x00306 }, + { 0x01FB1 , 0x003B1 , 0x00304 }, + { 0x01FB2 , 0x01F70 , 0x00345 }, + { 0x01FB3 , 0x003B1 , 0x00345 }, + { 0x01FB4 , 0x003AC , 0x00345 }, + { 0x01FB6 , 0x003B1 , 0x00342 }, + { 0x01FB7 , 0x01FB6 , 0x00345 }, + { 0x01FB8 , 0x00391 , 0x00306 }, + { 0x01FB9 , 0x00391 , 0x00304 }, + { 0x01FBA , 0x00391 , 0x00300 }, + { 0x01FBC , 0x00391 , 0x00345 }, + { 0x01FC1 , 0x000A8 , 0x00342 }, + { 0x01FC2 , 0x01F74 , 0x00345 }, + { 0x01FC3 , 0x003B7 , 0x00345 }, + { 0x01FC4 , 0x003AE , 0x00345 }, + { 0x01FC6 , 0x003B7 , 0x00342 }, + { 0x01FC7 , 0x01FC6 , 0x00345 }, + { 0x01FC8 , 0x00395 , 0x00300 }, + { 0x01FCA , 0x00397 , 0x00300 }, + { 0x01FCC , 0x00397 , 0x00345 }, + { 0x01FCD , 0x01FBF , 0x00300 }, + { 0x01FCE , 0x01FBF , 0x00301 }, + { 0x01FCF , 0x01FBF , 0x00342 }, + { 0x01FD0 , 0x003B9 , 0x00306 }, + { 0x01FD1 , 0x003B9 , 0x00304 }, + { 0x01FD2 , 0x003CA , 0x00300 }, + { 0x01FD6 , 0x003B9 , 0x00342 }, + { 0x01FD7 , 0x003CA , 0x00342 }, + { 0x01FD8 , 0x00399 , 0x00306 }, + { 0x01FD9 , 0x00399 , 0x00304 }, + { 0x01FDA , 0x00399 , 0x00300 }, + { 0x01FDD , 0x01FFE , 0x00300 }, + { 0x01FDE , 0x01FFE , 0x00301 }, + { 0x01FDF , 0x01FFE , 0x00342 }, + { 0x01FE0 , 0x003C5 , 0x00306 }, + { 0x01FE1 , 0x003C5 , 0x00304 }, + { 0x01FE2 , 0x003CB , 0x00300 }, + { 0x01FE4 , 0x003C1 , 0x00313 }, + { 0x01FE5 , 0x003C1 , 0x00314 }, + { 0x01FE6 , 0x003C5 , 0x00342 }, + { 0x01FE7 , 0x003CB , 0x00342 }, + { 0x01FE8 , 0x003A5 , 0x00306 }, + { 0x01FE9 , 0x003A5 , 0x00304 }, + { 0x01FEA , 0x003A5 , 0x00300 }, + { 0x01FEC , 0x003A1 , 0x00314 }, + { 0x01FED , 0x000A8 , 0x00300 }, + { 0x01FF2 , 0x01F7C , 0x00345 }, + { 0x01FF3 , 0x003C9 , 0x00345 }, + { 0x01FF4 , 0x003CE , 0x00345 }, + { 0x01FF6 , 0x003C9 , 0x00342 }, + { 0x01FF7 , 0x01FF6 , 0x00345 }, + { 0x01FF8 , 0x0039F , 0x00300 }, + { 0x01FFA , 0x003A9 , 0x00300 }, + { 0x01FFC , 0x003A9 , 0x00345 }, + { 0x0219A , 0x02190 , 0x00338 }, + { 0x0219B , 0x02192 , 0x00338 }, + { 0x021AE , 0x02194 , 0x00338 }, + { 0x021CD , 0x021D0 , 0x00338 }, + { 0x021CE , 0x021D4 , 0x00338 }, + { 0x021CF , 0x021D2 , 0x00338 }, + { 0x02204 , 0x02203 , 0x00338 }, + { 0x02209 , 0x02208 , 0x00338 }, + { 0x0220C , 0x0220B , 0x00338 }, + { 0x02224 , 0x02223 , 0x00338 }, + { 0x02226 , 0x02225 , 0x00338 }, + { 0x02241 , 0x0223C , 0x00338 }, + { 0x02244 , 0x02243 , 0x00338 }, + { 0x02247 , 0x02245 , 0x00338 }, + { 0x02249 , 0x02248 , 0x00338 }, + { 0x02260 , 0x0003D , 0x00338 }, + { 0x02262 , 0x02261 , 0x00338 }, + { 0x0226D , 0x0224D , 0x00338 }, + { 0x0226E , 0x0003C , 0x00338 }, + { 0x0226F , 0x0003E , 0x00338 }, + { 0x02270 , 0x02264 , 0x00338 }, + { 0x02271 , 0x02265 , 0x00338 }, + { 0x02274 , 0x02272 , 0x00338 }, + { 0x02275 , 0x02273 , 0x00338 }, + { 0x02278 , 0x02276 , 0x00338 }, + { 0x02279 , 0x02277 , 0x00338 }, + { 0x02280 , 0x0227A , 0x00338 }, + { 0x02281 , 0x0227B , 0x00338 }, + { 0x02284 , 0x02282 , 0x00338 }, + { 0x02285 , 0x02283 , 0x00338 }, + { 0x02288 , 0x02286 , 0x00338 }, + { 0x02289 , 0x02287 , 0x00338 }, + { 0x022AC , 0x022A2 , 0x00338 }, + { 0x022AD , 0x022A8 , 0x00338 }, + { 0x022AE , 0x022A9 , 0x00338 }, + { 0x022AF , 0x022AB , 0x00338 }, + { 0x022E0 , 0x0227C , 0x00338 }, + { 0x022E1 , 0x0227D , 0x00338 }, + { 0x022E2 , 0x02291 , 0x00338 }, + { 0x022E3 , 0x02292 , 0x00338 }, + { 0x022EA , 0x022B2 , 0x00338 }, + { 0x022EB , 0x022B3 , 0x00338 }, + { 0x022EC , 0x022B4 , 0x00338 }, + { 0x022ED , 0x022B5 , 0x00338 }, + { 0x0304C , 0x0304B , 0x03099 }, + { 0x0304E , 0x0304D , 0x03099 }, + { 0x03050 , 0x0304F , 0x03099 }, + { 0x03052 , 0x03051 , 0x03099 }, + { 0x03054 , 0x03053 , 0x03099 }, + { 0x03056 , 0x03055 , 0x03099 }, + { 0x03058 , 0x03057 , 0x03099 }, + { 0x0305A , 0x03059 , 0x03099 }, + { 0x0305C , 0x0305B , 0x03099 }, + { 0x0305E , 0x0305D , 0x03099 }, + { 0x03060 , 0x0305F , 0x03099 }, + { 0x03062 , 0x03061 , 0x03099 }, + { 0x03065 , 0x03064 , 0x03099 }, + { 0x03067 , 0x03066 , 0x03099 }, + { 0x03069 , 0x03068 , 0x03099 }, + { 0x03070 , 0x0306F , 0x03099 }, + { 0x03071 , 0x0306F , 0x0309A }, + { 0x03073 , 0x03072 , 0x03099 }, + { 0x03074 , 0x03072 , 0x0309A }, + { 0x03076 , 0x03075 , 0x03099 }, + { 0x03077 , 0x03075 , 0x0309A }, + { 0x03079 , 0x03078 , 0x03099 }, + { 0x0307A , 0x03078 , 0x0309A }, + { 0x0307C , 0x0307B , 0x03099 }, + { 0x0307D , 0x0307B , 0x0309A }, + { 0x03094 , 0x03046 , 0x03099 }, + { 0x0309E , 0x0309D , 0x03099 }, + { 0x030AC , 0x030AB , 0x03099 }, + { 0x030AE , 0x030AD , 0x03099 }, + { 0x030B0 , 0x030AF , 0x03099 }, + { 0x030B2 , 0x030B1 , 0x03099 }, + { 0x030B4 , 0x030B3 , 0x03099 }, + { 0x030B6 , 0x030B5 , 0x03099 }, + { 0x030B8 , 0x030B7 , 0x03099 }, + { 0x030BA , 0x030B9 , 0x03099 }, + { 0x030BC , 0x030BB , 0x03099 }, + { 0x030BE , 0x030BD , 0x03099 }, + { 0x030C0 , 0x030BF , 0x03099 }, + { 0x030C2 , 0x030C1 , 0x03099 }, + { 0x030C5 , 0x030C4 , 0x03099 }, + { 0x030C7 , 0x030C6 , 0x03099 }, + { 0x030C9 , 0x030C8 , 0x03099 }, + { 0x030D0 , 0x030CF , 0x03099 }, + { 0x030D1 , 0x030CF , 0x0309A }, + { 0x030D3 , 0x030D2 , 0x03099 }, + { 0x030D4 , 0x030D2 , 0x0309A }, + { 0x030D6 , 0x030D5 , 0x03099 }, + { 0x030D7 , 0x030D5 , 0x0309A }, + { 0x030D9 , 0x030D8 , 0x03099 }, + { 0x030DA , 0x030D8 , 0x0309A }, + { 0x030DC , 0x030DB , 0x03099 }, + { 0x030DD , 0x030DB , 0x0309A }, + { 0x030F4 , 0x030A6 , 0x03099 }, + { 0x030F7 , 0x030EF , 0x03099 }, + { 0x030F8 , 0x030F0 , 0x03099 }, + { 0x030F9 , 0x030F1 , 0x03099 }, + { 0x030FA , 0x030F2 , 0x03099 }, + { 0x030FE , 0x030FD , 0x03099 }, + { 0x1109A , 0x11099 , 0x110BA }, + { 0x1109C , 0x1109B , 0x110BA }, + { 0x110AB , 0x110A5 , 0x110BA }, +}; + #endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */ + diff --git a/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c b/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c index 7d7d9713c..964ea2bea 100644 --- a/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c +++ b/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c @@ -38,7 +38,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_string_sprintf.c 189435 2009-03- * here. This is only used to format error messages, so doesn't * require any floating-point support or field-width handling. */ - +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif #include <stdio.h> #include "archive_string.h" @@ -129,7 +131,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt, break; case 'c': s = va_arg(ap, int); - archive_strappend_char(as, s); + archive_strappend_char(as, (char)s); break; case 'd': switch(long_flag) { @@ -146,7 +148,9 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt, pw = va_arg(ap, wchar_t *); if (pw == NULL) pw = L"(null)"; - archive_string_append_from_wcs(as, pw, wcslen(pw)); + if (archive_string_append_from_wcs(as, pw, + wcslen(pw)) != 0 && errno == ENOMEM) + __archive_errx(1, "Out of memory"); break; default: p2 = va_arg(ap, char *); @@ -160,7 +164,9 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt, pw = va_arg(ap, wchar_t *); if (pw == NULL) pw = L"(null)"; - archive_string_append_from_wcs(as, pw, wcslen(pw)); + if (archive_string_append_from_wcs(as, pw, + wcslen(pw)) != 0 && errno == ENOMEM) + __archive_errx(1, "Out of memory"); break; case 'o': case 'u': case 'x': case 'X': /* Common handling for unsigned integer formats. */ diff --git a/Utilities/cmlibarchive/libarchive/archive_util.3 b/Utilities/cmlibarchive/libarchive/archive_util.3 index cd05d03f1..99ab842a2 100644 --- a/Utilities/cmlibarchive/libarchive/archive_util.3 +++ b/Utilities/cmlibarchive/libarchive/archive_util.3 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_util.3 201098 2009-12-28 02:58:14Z kientzle $ +.\" $FreeBSD$ .\" -.Dd January 8, 2005 +.Dd February 2, 2012 .Dt ARCHIVE_UTIL 3 .Os .Sh NAME @@ -43,6 +43,8 @@ .Nm archive_position , .Nm archive_set_error .Nd libarchive utility functions +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft void diff --git a/Utilities/cmlibarchive/libarchive/archive_util.c b/Utilities/cmlibarchive/libarchive/archive_util.c index e0852a3b5..34d8081cb 100644 --- a/Utilities/cmlibarchive/libarchive/archive_util.c +++ b/Utilities/cmlibarchive/libarchive/archive_util.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009,2010 Michihiro NAKAJIMA + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * Copyright (c) 2003-2007 Tim Kientzle * All rights reserved. * @@ -50,6 +50,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1 #include "archive_private.h" #include "archive_string.h" +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + /* Generic initialization of 'struct archive' objects. */ int __archive_clean(struct archive *a) @@ -239,12 +243,13 @@ __archive_mktemp(const char *tmpdir) errno = ENOMEM; goto exit_tmpfile; } - GetTempPathW(l, tmp); + GetTempPathW((DWORD)l, tmp); archive_wstrcpy(&temp_name, tmp); free(tmp); } else { - archive_wstring_append_from_mbs(&temp_name, tmpdir, - strlen(tmpdir)); + if (archive_wstring_append_from_mbs(&temp_name, tmpdir, + strlen(tmpdir)) < 0) + goto exit_tmpfile; if (temp_name.s[temp_name.length-1] != L'/') archive_wstrappend_wchar(&temp_name, L'/'); } @@ -292,7 +297,8 @@ __archive_mktemp(const char *tmpdir) /* Generate a random file name through CryptGenRandom(). */ p = xp; - if (!CryptGenRandom(hProv, (ep - p)*sizeof(wchar_t), (BYTE*)p)) { + if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t), + (BYTE*)p)) { la_dosmaperr(GetLastError()); goto exit_tmpfile; } @@ -384,6 +390,7 @@ __archive_mktemp(const char *tmpdir) fd = mkstemp(temp_name.s); if (fd < 0) goto exit_tmpfile; + __archive_ensure_cloexec_flag(fd); unlink(temp_name.s); exit_tmpfile: archive_string_free(&temp_name); @@ -437,7 +444,8 @@ __archive_mktemp(const char *tmpdir) archive_strcat(&temp_name, "XXXXXXXXXX"); ep = temp_name.s + archive_strlen(&temp_name); - fd = open("/dev/random", O_RDONLY); + fd = open("/dev/random", O_RDONLY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); if (fd < 0) seed = time(NULL); else { @@ -451,10 +459,12 @@ __archive_mktemp(const char *tmpdir) p = tp; while (p < ep) *p++ = num[((unsigned)rand_r(&seed)) % sizeof(num)]; - fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR, 0600); + fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, + 0600); } while (fd < 0 && errno == EEXIST); if (fd < 0) goto exit_tmpfile; + __archive_ensure_cloexec_flag(fd); unlink(temp_name.s); exit_tmpfile: archive_string_free(&temp_name); @@ -463,3 +473,29 @@ exit_tmpfile: #endif /* HAVE_MKSTEMP */ #endif /* !_WIN32 || __CYGWIN__ */ + +/* + * Set FD_CLOEXEC flag to a file descriptor if it is not set. + * We have to set the flag if the platform does not provide O_CLOEXEC + * or F_DUPFD_CLOEXEC flags. + * + * Note: This function is absolutely called after creating a new file + * descriptor even if the platform seemingly provides O_CLOEXEC or + * F_DUPFD_CLOEXEC macros because it is possible that the platform + * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it. + */ +void +__archive_ensure_cloexec_flag(int fd) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + (void)fd; /* UNSED */ +#else + int flags; + + if (fd >= 0) { + flags = fcntl(fd, F_GETFD); + if (flags != -1 && (flags & FD_CLOEXEC) == 0) + fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + } +#endif +} diff --git a/Utilities/cmlibarchive/libarchive/archive_virtual.c b/Utilities/cmlibarchive/libarchive/archive_virtual.c index 752dc17c2..0c4155f21 100644 --- a/Utilities/cmlibarchive/libarchive/archive_virtual.c +++ b/Utilities/cmlibarchive/libarchive/archive_virtual.c @@ -67,8 +67,17 @@ archive_read_close(struct archive *a) } int +archive_write_fail(struct archive *a) +{ + a->state = ARCHIVE_STATE_FATAL; + return a->state; +} + +int archive_write_free(struct archive *a) { + if (a == NULL) + return (ARCHIVE_OK); return ((a->vtable->archive_free)(a)); } @@ -77,13 +86,15 @@ archive_write_free(struct archive *a) int archive_write_finish(struct archive *a) { - return ((a->vtable->archive_free)(a)); + return archive_write_free(a); } #endif int archive_read_free(struct archive *a) { + if (a == NULL) + return (ARCHIVE_OK); return ((a->vtable->archive_free)(a)); } @@ -92,7 +103,7 @@ archive_read_free(struct archive *a) int archive_read_finish(struct archive *a) { - return ((a->vtable->archive_free)(a)); + return archive_read_free(a); } #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_windows.c b/Utilities/cmlibarchive/libarchive/archive_windows.c index 8f5d566a5..d3bf758bb 100644 --- a/Utilities/cmlibarchive/libarchive/archive_windows.c +++ b/Utilities/cmlibarchive/libarchive/archive_windows.c @@ -48,6 +48,7 @@ #include "archive_platform.h" #include "archive_private.h" +#include "archive_entry.h" #include <ctype.h> #include <errno.h> #include <stddef.h> @@ -109,7 +110,7 @@ getino(struct ustat *ub) ULARGE_INTEGER ino64; ino64.QuadPart = ub->st_ino; /* I don't know this hashing is correct way */ - return (ino64.LowPart ^ (ino64.LowPart >> INOSIZE)); + return ((ino_t)(ino64.LowPart ^ (ino64.LowPart >> INOSIZE))); } /* @@ -153,7 +154,7 @@ __la_win_permissive_name_w(const wchar_t *wname) if (l == 0) return (NULL); /* NOTE: GetFullPathNameW has a bug that if the length of the file - * name is just one that return imcomplete buffer size. Thus, we + * name is just 1 then it returns incomplete buffer size. Thus, we * have to add three to the size to allocate a sufficient buffer * size for the full-pathname of the file name. */ l += 3; @@ -424,7 +425,7 @@ __la_read(int fd, void *buf, size_t nbytes) /* Convert Windows FILETIME to UTC */ __inline static void -fileTimeToUTC(const FILETIME *filetime, time_t *time, long *ns) +fileTimeToUTC(const FILETIME *filetime, time_t *t, long *ns) { ULARGE_INTEGER utc; @@ -432,10 +433,10 @@ fileTimeToUTC(const FILETIME *filetime, time_t *time, long *ns) utc.LowPart = filetime->dwLowDateTime; if (utc.QuadPart >= EPOC_TIME) { utc.QuadPart -= EPOC_TIME; - *time = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */ + *t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */ *ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */ } else { - *time = 0; + *t = 0; *ns = 0; } } @@ -458,7 +459,7 @@ __hstat(HANDLE handle, struct ustat *st) ULARGE_INTEGER ino64; DWORD ftype; mode_t mode; - time_t time; + time_t t; long ns; switch (ftype = GetFileType(handle)) { @@ -515,14 +516,14 @@ __hstat(HANDLE handle, struct ustat *st) mode |= S_IFREG; st->st_mode = mode; - fileTimeToUTC(&info.ftLastAccessTime, &time, &ns); - st->st_atime = time; + fileTimeToUTC(&info.ftLastAccessTime, &t, &ns); + st->st_atime = t; st->st_atime_nsec = ns; - fileTimeToUTC(&info.ftLastWriteTime, &time, &ns); - st->st_mtime = time; + fileTimeToUTC(&info.ftLastWriteTime, &t, &ns); + st->st_mtime = t; st->st_mtime_nsec = ns; - fileTimeToUTC(&info.ftCreationTime, &time, &ns); - st->st_ctime = time; + fileTimeToUTC(&info.ftCreationTime, &t, &ns); + st->st_ctime = t; st->st_ctime_nsec = ns; st->st_size = ((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1)) @@ -558,7 +559,7 @@ copy_stat(struct stat *st, struct ustat *us) st->st_ino = getino(us); st->st_mode = us->st_mode; st->st_nlink = us->st_nlink; - st->st_size = us->st_size; + st->st_size = (off_t)us->st_size; st->st_uid = us->st_uid; st->st_dev = us->st_dev; st->st_rdev = us->st_rdev; @@ -632,35 +633,22 @@ __la_stat(const char *path, struct stat *st) * This waitpid is limited implementation. */ pid_t -__la_waitpid(pid_t wpid, int *status, int option) +__la_waitpid(HANDLE child, int *status, int option) { - HANDLE child; - DWORD cs, ret; + DWORD cs; (void)option;/* UNUSED */ - *status = 0; - child = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, wpid); - if (child == NULL) { - la_dosmaperr(GetLastError()); - return (-1); - } - ret = WaitForSingleObject(child, INFINITE); - if (ret == WAIT_FAILED) { - CloseHandle(child); - la_dosmaperr(GetLastError()); - return (-1); - } - if (GetExitCodeProcess(child, &cs) == 0) { - CloseHandle(child); - la_dosmaperr(GetLastError()); - return (-1); - } - if (cs == STILL_ACTIVE) - *status = 0x100; - else - *status = (int)(cs & 0xff); - CloseHandle(child); - return (wpid); + do { + if (GetExitCodeProcess(child, &cs) == 0) { + CloseHandle(child); + la_dosmaperr(GetLastError()); + *status = 0; + return (-1); + } + } while (cs == STILL_ACTIVE); + + *status = (int)(cs & 0xff); + return (0); } ssize_t @@ -691,6 +679,113 @@ __la_write(int fd, const void *buf, size_t nbytes) } /* + * Replace the Windows path separator '\' with '/'. + */ +static int +replace_pathseparator(struct archive_wstring *ws, const wchar_t *wp) +{ + wchar_t *w; + size_t path_length; + + if (wp == NULL) + return(0); + if (wcschr(wp, L'\\') == NULL) + return(0); + path_length = wcslen(wp); + if (archive_wstring_ensure(ws, path_length) == NULL) + return(-1); + archive_wstrncpy(ws, wp, path_length); + for (w = ws->s; *w; w++) { + if (*w == L'\\') + *w = L'/'; + } + return(1); +} + +static int +fix_pathseparator(struct archive_entry *entry) +{ + struct archive_wstring ws; + const wchar_t *wp; + int ret = ARCHIVE_OK; + + archive_string_init(&ws); + wp = archive_entry_pathname_w(entry); + switch (replace_pathseparator(&ws, wp)) { + case 0: /* Not replaced. */ + break; + case 1: /* Replaced. */ + archive_entry_copy_pathname_w(entry, ws.s); + break; + default: + ret = ARCHIVE_FAILED; + } + wp = archive_entry_hardlink_w(entry); + switch (replace_pathseparator(&ws, wp)) { + case 0: /* Not replaced. */ + break; + case 1: /* Replaced. */ + archive_entry_copy_hardlink_w(entry, ws.s); + break; + default: + ret = ARCHIVE_FAILED; + } + wp = archive_entry_symlink_w(entry); + switch (replace_pathseparator(&ws, wp)) { + case 0: /* Not replaced. */ + break; + case 1: /* Replaced. */ + archive_entry_copy_symlink_w(entry, ws.s); + break; + default: + ret = ARCHIVE_FAILED; + } + archive_wstring_free(&ws); + return(ret); +} + +struct archive_entry * +__la_win_entry_in_posix_pathseparator(struct archive_entry *entry) +{ + struct archive_entry *entry_main; + const wchar_t *wp; + int has_backslash = 0; + int ret; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wcschr(wp, L'\\') != NULL) + has_backslash = 1; + if (!has_backslash) { + wp = archive_entry_hardlink_w(entry); + if (wp != NULL && wcschr(wp, L'\\') != NULL) + has_backslash = 1; + } + if (!has_backslash) { + wp = archive_entry_symlink_w(entry); + if (wp != NULL && wcschr(wp, L'\\') != NULL) + has_backslash = 1; + } + /* + * If there is no backslach chars, return the original. + */ + if (!has_backslash) + return (entry); + + /* Copy entry so we can modify it as needed. */ + entry_main = archive_entry_clone(entry); + if (entry_main == NULL) + return (NULL); + /* Replace the Windows path-separator '\' with '/'. */ + ret = fix_pathseparator(entry_main); + if (ret < ARCHIVE_WARN) { + archive_entry_free(entry_main); + return (NULL); + } + return (entry_main); +} + + +/* * The following function was modified from PostgreSQL sources and is * subject to the copyright below. */ @@ -796,7 +891,7 @@ __la_dosmaperr(unsigned long e) return; } - for (i = 0; i < sizeof(doserrors); i++) + for (i = 0; i < (int)sizeof(doserrors); i++) { if (doserrors[i].winerr == e) { diff --git a/Utilities/cmlibarchive/libarchive/archive_windows.h b/Utilities/cmlibarchive/libarchive/archive_windows.h index c581af317..620810c1c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_windows.h +++ b/Utilities/cmlibarchive/libarchive/archive_windows.h @@ -49,6 +49,9 @@ #define LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED /* Start of configuration for native Win32 */ +#ifndef MINGW_HAS_SECURE_API +#define MINGW_HAS_SECURE_API 1 +#endif #include <errno.h> #define set_errno(val) ((errno)=val) @@ -72,7 +75,6 @@ //#define EFTYPE 7 #if defined(_MSC_VER) -/* TODO: Fix the code, don't suppress the warnings. */ #pragma warning(push,1) #pragma warning(disable:4761) /* integral size mismatch in argument; conversion supplied */ #endif @@ -95,8 +97,14 @@ #ifndef fileno #define fileno _fileno #endif +#ifdef fstat +#undef fstat +#endif #define fstat __la_fstat #if !defined(__BORLANDC__) +#ifdef lseek +#undef lseek +#endif #define lseek _lseeki64 #else #define lseek __la_lseek @@ -108,6 +116,9 @@ #if !defined(__BORLANDC__) #define setmode _setmode #endif +#ifdef stat +#undef stat +#endif #define stat(path,stref) __la_stat(path,stref) #if !defined(__BORLANDC__) #define strdup _strdup @@ -257,7 +268,7 @@ extern __int64 __la_lseek(int fd, __int64 offset, int whence); extern int __la_open(const char *path, int flags, ...); extern ssize_t __la_read(int fd, void *buf, size_t nbytes); extern int __la_stat(const char *path, struct stat *st); -extern pid_t __la_waitpid(pid_t wpid, int *status, int option); +extern pid_t __la_waitpid(HANDLE child, int *status, int option); extern ssize_t __la_write(int fd, const void *buf, size_t nbytes); #define _stat64i32(path, st) __la_stat(path, st) @@ -270,6 +281,8 @@ extern wchar_t *__la_win_permissive_name(const char *name); extern wchar_t *__la_win_permissive_name_w(const wchar_t *wname); extern void __la_dosmaperr(unsigned long e); #define la_dosmaperr(e) __la_dosmaperr(e) +extern struct archive_entry *__la_win_entry_in_posix_pathseparator( + struct archive_entry *); #if defined(HAVE_WCRTOMB) && defined(__BORLANDC__) typedef int mbstate_t; @@ -278,14 +291,14 @@ size_t wcrtomb(char *, wchar_t, mbstate_t *); #if defined(_MSC_VER) && _MSC_VER < 1300 WINBASEAPI BOOL WINAPI GetVolumePathNameW( - LPCWSTR lpszFileName, - LPWSTR lpszVolumePathName, - DWORD cchBufferLength - ); + LPCWSTR lpszFileName, + LPWSTR lpszVolumePathName, + DWORD cchBufferLength + ); # if _WIN32_WINNT < 0x0500 /* windows.h not providing 0x500 API */ typedef struct _FILE_ALLOCATED_RANGE_BUFFER { - LARGE_INTEGER FileOffset; - LARGE_INTEGER Length; + LARGE_INTEGER FileOffset; + LARGE_INTEGER Length; } FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER; # define FSCTL_SET_SPARSE \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_WRITE_DATA) diff --git a/Utilities/cmlibarchive/libarchive/archive_write.3 b/Utilities/cmlibarchive/libarchive/archive_write.3 index f87386a8b..228bc2cb8 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write.3 @@ -22,14 +22,16 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $ +.\" $FreeBSD$ .\" -.Dd March 23, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_WRITE 3 .Os .Sh NAME .Nm archive_write .Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Sh DESCRIPTION diff --git a/Utilities/cmlibarchive/libarchive/archive_write.c b/Utilities/cmlibarchive/libarchive/archive_write.c index b4b3867f0..b296069e9 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write.c +++ b/Utilities/cmlibarchive/libarchive/archive_write.c @@ -232,6 +232,10 @@ __archive_write_filter(struct archive_write_filter *f, int r; if (length == 0) return(ARCHIVE_OK); + if (f->write == NULL) + /* If unset, a fatal error has already ocuured, so this filter + * didn't open. We cannot write anything. */ + return(ARCHIVE_FATAL); r = (f->write)(f, buff, length); f->bytes_written += length; return (r); @@ -323,43 +327,43 @@ archive_write_client_write(struct archive_write_filter *f, { struct archive_write *a = (struct archive_write *)f->archive; struct archive_none *state = (struct archive_none *)f->data; - const char *buff = (const char *)_buff; - ssize_t remaining, to_copy; - ssize_t bytes_written; - - remaining = length; - - /* - * If there is no buffer for blocking, just pass the data - * straight through to the client write callback. In - * particular, this supports "no write delay" operation for - * special applications. Just set the block size to zero. - */ - if (state->buffer_size == 0) { - while (remaining > 0) { - bytes_written = (a->client_writer)(&a->archive, - a->client_data, buff, remaining); - if (bytes_written <= 0) - return (ARCHIVE_FATAL); - remaining -= bytes_written; - buff += bytes_written; - } - return (ARCHIVE_OK); - } - - /* If the copy buffer isn't empty, try to fill it. */ - if (state->avail < state->buffer_size) { - /* If buffer is not empty... */ - /* ... copy data into buffer ... */ - to_copy = ((size_t)remaining > state->avail) ? + const char *buff = (const char *)_buff; + ssize_t remaining, to_copy; + ssize_t bytes_written; + + remaining = length; + + /* + * If there is no buffer for blocking, just pass the data + * straight through to the client write callback. In + * particular, this supports "no write delay" operation for + * special applications. Just set the block size to zero. + */ + if (state->buffer_size == 0) { + while (remaining > 0) { + bytes_written = (a->client_writer)(&a->archive, + a->client_data, buff, remaining); + if (bytes_written <= 0) + return (ARCHIVE_FATAL); + remaining -= bytes_written; + buff += bytes_written; + } + return (ARCHIVE_OK); + } + + /* If the copy buffer isn't empty, try to fill it. */ + if (state->avail < state->buffer_size) { + /* If buffer is not empty... */ + /* ... copy data into buffer ... */ + to_copy = ((size_t)remaining > state->avail) ? state->avail : (size_t)remaining; - memcpy(state->next, buff, to_copy); - state->next += to_copy; - state->avail -= to_copy; - buff += to_copy; - remaining -= to_copy; - /* ... if it's full, write it out. */ - if (state->avail == 0) { + memcpy(state->next, buff, to_copy); + state->next += to_copy; + state->avail -= to_copy; + buff += to_copy; + remaining -= to_copy; + /* ... if it's full, write it out. */ + if (state->avail == 0) { char *p = state->buffer; size_t to_write = state->buffer_size; while (to_write > 0) { @@ -375,70 +379,72 @@ archive_write_client_write(struct archive_write_filter *f, p += bytes_written; to_write -= bytes_written; } - state->next = state->buffer; - state->avail = state->buffer_size; - } - } - - while ((size_t)remaining > state->buffer_size) { - /* Write out full blocks directly to client. */ - bytes_written = (a->client_writer)(&a->archive, - a->client_data, buff, state->buffer_size); - if (bytes_written <= 0) - return (ARCHIVE_FATAL); - buff += bytes_written; - remaining -= bytes_written; - } - - if (remaining > 0) { - /* Copy last bit into copy buffer. */ - memcpy(state->next, buff, remaining); - state->next += remaining; - state->avail -= remaining; - } - return (ARCHIVE_OK); + state->next = state->buffer; + state->avail = state->buffer_size; + } + } + + while ((size_t)remaining >= state->buffer_size) { + /* Write out full blocks directly to client. */ + bytes_written = (a->client_writer)(&a->archive, + a->client_data, buff, state->buffer_size); + if (bytes_written <= 0) + return (ARCHIVE_FATAL); + buff += bytes_written; + remaining -= bytes_written; + } + + if (remaining > 0) { + /* Copy last bit into copy buffer. */ + memcpy(state->next, buff, remaining); + state->next += remaining; + state->avail -= remaining; + } + return (ARCHIVE_OK); } static int archive_write_client_close(struct archive_write_filter *f) { struct archive_write *a = (struct archive_write *)f->archive; - struct archive_none *state = (struct archive_none *)f->data; - ssize_t block_length; - ssize_t target_block_length; - ssize_t bytes_written; - int ret = ARCHIVE_OK; - - /* If there's pending data, pad and write the last block */ - if (state->next != state->buffer) { - block_length = state->buffer_size - state->avail; - - /* Tricky calculation to determine size of last block */ - if (a->bytes_in_last_block <= 0) - /* Default or Zero: pad to full block */ - target_block_length = a->bytes_per_block; - else - /* Round to next multiple of bytes_in_last_block. */ - target_block_length = a->bytes_in_last_block * - ( (block_length + a->bytes_in_last_block - 1) / - a->bytes_in_last_block); - if (target_block_length > a->bytes_per_block) - target_block_length = a->bytes_per_block; - if (block_length < target_block_length) { - memset(state->next, 0, - target_block_length - block_length); - block_length = target_block_length; - } - bytes_written = (a->client_writer)(&a->archive, - a->client_data, state->buffer, block_length); - ret = bytes_written <= 0 ? ARCHIVE_FATAL : ARCHIVE_OK; - } + struct archive_none *state = (struct archive_none *)f->data; + ssize_t block_length; + ssize_t target_block_length; + ssize_t bytes_written; + int ret = ARCHIVE_OK; + + /* If there's pending data, pad and write the last block */ + if (state->next != state->buffer) { + block_length = state->buffer_size - state->avail; + + /* Tricky calculation to determine size of last block */ + if (a->bytes_in_last_block <= 0) + /* Default or Zero: pad to full block */ + target_block_length = a->bytes_per_block; + else + /* Round to next multiple of bytes_in_last_block. */ + target_block_length = a->bytes_in_last_block * + ( (block_length + a->bytes_in_last_block - 1) / + a->bytes_in_last_block); + if (target_block_length > a->bytes_per_block) + target_block_length = a->bytes_per_block; + if (block_length < target_block_length) { + memset(state->next, 0, + target_block_length - block_length); + block_length = target_block_length; + } + bytes_written = (a->client_writer)(&a->archive, + a->client_data, state->buffer, block_length); + ret = bytes_written <= 0 ? ARCHIVE_FATAL : ARCHIVE_OK; + } if (a->client_closer) (*a->client_closer)(&a->archive, a->client_data); free(state->buffer); - free(state); - a->client_data = NULL; - return (ret); + free(state); + /* Clear the close handler myself not to be called again. */ + f->close = NULL; + a->client_data = NULL; + return (ret); } /* @@ -623,7 +629,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry) if (a->skip_file_set && archive_entry_dev_is_set(entry) && archive_entry_ino_is_set(entry) && - archive_entry_dev(entry) == a->skip_file_dev && + archive_entry_dev(entry) == (dev_t)a->skip_file_dev && archive_entry_ino64(entry) == a->skip_file_ino) { archive_set_error(&a->archive, 0, "Can't add archive to itself"); diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c new file mode 100644 index 000000000..81dd683aa --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 2012 Ondrej Holy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#include "archive.h" +#include "archive_private.h" + +/* A table that maps filter codes to functions. */ +static +struct { int code; int (*setter)(struct archive *); } codes[] = +{ + { ARCHIVE_FILTER_NONE, archive_write_add_filter_none }, + { ARCHIVE_FILTER_GZIP, archive_write_add_filter_gzip }, + { ARCHIVE_FILTER_BZIP2, archive_write_add_filter_bzip2 }, + { ARCHIVE_FILTER_COMPRESS, archive_write_add_filter_compress }, + { ARCHIVE_FILTER_GRZIP, archive_write_add_filter_grzip }, + { ARCHIVE_FILTER_LRZIP, archive_write_add_filter_lrzip }, + { ARCHIVE_FILTER_LZIP, archive_write_add_filter_lzip }, + { ARCHIVE_FILTER_LZMA, archive_write_add_filter_lzma }, + { ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip }, + { ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode }, + { ARCHIVE_FILTER_XZ, archive_write_add_filter_xz }, + { -1, NULL } +}; + +int +archive_write_add_filter(struct archive *a, int code) +{ + int i; + + for (i = 0; codes[i].code != -1; i++) { + if (code == codes[i].code) + return ((codes[i].setter)(a)); + } + + archive_set_error(a, EINVAL, "No such filter"); + return (ARCHIVE_FATAL); +} diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c new file mode 100644 index 000000000..85eb087b0 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c @@ -0,0 +1,314 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" +#include "archive_write_private.h" + +#define LBYTES 57 + +struct private_b64encode { + int mode; + struct archive_string name; + struct archive_string encoded_buff; + size_t bs; + size_t hold_len; + unsigned char hold[LBYTES]; +}; + +static int archive_filter_b64encode_options(struct archive_write_filter *, + const char *, const char *); +static int archive_filter_b64encode_open(struct archive_write_filter *); +static int archive_filter_b64encode_write(struct archive_write_filter *, + const void *, size_t); +static int archive_filter_b64encode_close(struct archive_write_filter *); +static int archive_filter_b64encode_free(struct archive_write_filter *); +static void b64_encode(struct archive_string *, const unsigned char *, size_t); +static int64_t atol8(const char *, size_t); + +static const char base64[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' +}; + +/* + * Add a compress filter to this write handle. + */ +int +archive_write_add_filter_b64encode(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct private_b64encode *state; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_uu"); + + state = (struct private_b64encode *)calloc(1, sizeof(*state)); + if (state == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for b64encode filter"); + return (ARCHIVE_FATAL); + } + archive_strcpy(&state->name, "-"); + state->mode = 0644; + + f->data = state; + f->name = "b64encode"; + f->code = ARCHIVE_FILTER_UU; + f->open = archive_filter_b64encode_open; + f->options = archive_filter_b64encode_options; + f->write = archive_filter_b64encode_write; + f->close = archive_filter_b64encode_close; + f->free = archive_filter_b64encode_free; + + return (ARCHIVE_OK); +} + +/* + * Set write options. + */ +static int +archive_filter_b64encode_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct private_b64encode *state = (struct private_b64encode *)f->data; + + if (strcmp(key, "mode") == 0) { + if (value == NULL) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "mode option requires octal digits"); + return (ARCHIVE_FAILED); + } + state->mode = (int)atol8(value, strlen(value)) & 0777; + return (ARCHIVE_OK); + } else if (strcmp(key, "name") == 0) { + if (value == NULL) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "name option requires a string"); + return (ARCHIVE_FAILED); + } + archive_strcpy(&state->name, value); + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +/* + * Setup callback. + */ +static int +archive_filter_b64encode_open(struct archive_write_filter *f) +{ + struct private_b64encode *state = (struct private_b64encode *)f->data; + size_t bs = 65536, bpb; + int ret; + + ret = __archive_write_open_filter(f->next_filter); + if (ret != ARCHIVE_OK) + return (ret); + + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + + state->bs = bs; + if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for b64encode buffer"); + return (ARCHIVE_FATAL); + } + + archive_string_sprintf(&state->encoded_buff, "begin-base64 %o %s\n", + state->mode, state->name.s); + + f->data = state; + return (0); +} + +static void +b64_encode(struct archive_string *as, const unsigned char *p, size_t len) +{ + int c; + + for (; len >= 3; p += 3, len -= 3) { + c = p[0] >> 2; + archive_strappend_char(as, base64[c]); + c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4); + archive_strappend_char(as, base64[c]); + c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6); + archive_strappend_char(as, base64[c]); + c = p[2] & 0x3f; + archive_strappend_char(as, base64[c]); + } + if (len > 0) { + c = p[0] >> 2; + archive_strappend_char(as, base64[c]); + c = (p[0] & 0x03) << 4; + if (len == 1) { + archive_strappend_char(as, base64[c]); + archive_strappend_char(as, '='); + archive_strappend_char(as, '='); + } else { + c |= (p[1] & 0xf0) >> 4; + archive_strappend_char(as, base64[c]); + c = (p[1] & 0x0f) << 2; + archive_strappend_char(as, base64[c]); + archive_strappend_char(as, '='); + } + } + archive_strappend_char(as, '\n'); +} + +/* + * Write data to the encoded stream. + */ +static int +archive_filter_b64encode_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_b64encode *state = (struct private_b64encode *)f->data; + const unsigned char *p = buff; + int ret = ARCHIVE_OK; + + if (length == 0) + return (ret); + + if (state->hold_len) { + while (state->hold_len < LBYTES && length > 0) { + state->hold[state->hold_len++] = *p++; + length--; + } + if (state->hold_len < LBYTES) + return (ret); + b64_encode(&state->encoded_buff, state->hold, LBYTES); + state->hold_len = 0; + } + + for (; length >= LBYTES; length -= LBYTES, p += LBYTES) + b64_encode(&state->encoded_buff, p, LBYTES); + + /* Save remaining bytes. */ + if (length > 0) { + memcpy(state->hold, p, length); + state->hold_len = length; + } + while (archive_strlen(&state->encoded_buff) >= state->bs) { + ret = __archive_write_filter(f->next_filter, + state->encoded_buff.s, state->bs); + memmove(state->encoded_buff.s, + state->encoded_buff.s + state->bs, + state->encoded_buff.length - state->bs); + state->encoded_buff.length -= state->bs; + } + + return (ret); +} + + +/* + * Finish the compression... + */ +static int +archive_filter_b64encode_close(struct archive_write_filter *f) +{ + struct private_b64encode *state = (struct private_b64encode *)f->data; + int ret, ret2; + + /* Flush remaining bytes. */ + if (state->hold_len != 0) + b64_encode(&state->encoded_buff, state->hold, state->hold_len); + archive_string_sprintf(&state->encoded_buff, "====\n"); + /* Write the last block */ + archive_write_set_bytes_in_last_block(f->archive, 1); + ret = __archive_write_filter(f->next_filter, + state->encoded_buff.s, archive_strlen(&state->encoded_buff)); + ret2 = __archive_write_close_filter(f->next_filter); + if (ret > ret2) + ret = ret2; + return (ret); +} + +static int +archive_filter_b64encode_free(struct archive_write_filter *f) +{ + struct private_b64encode *state = (struct private_b64encode *)f->data; + + archive_string_free(&state->name); + archive_string_free(&state->encoded_buff); + free(state); + return (ARCHIVE_OK); +} + +static int64_t +atol8(const char *p, size_t char_cnt) +{ + int64_t l; + int digit; + + l = 0; + while (char_cnt-- > 0) { + if (*p >= '0' && *p <= '7') + digit = *p - '0'; + else + break; + p++; + l <<= 3; + l |= digit; + } + return (l); +} + diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c new file mode 100644 index 000000000..e4cba4afa --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include "archive.h" +#include "archive_private.h" + +/* A table that maps names to functions. */ +static +struct { const char *name; int (*setter)(struct archive *); } names[] = +{ + { "b64encode", archive_write_add_filter_b64encode }, + { "bzip2", archive_write_add_filter_bzip2 }, + { "compress", archive_write_add_filter_compress }, + { "grzip", archive_write_add_filter_grzip }, + { "gzip", archive_write_add_filter_gzip }, + { "lrzip", archive_write_add_filter_lrzip }, + { "lzip", archive_write_add_filter_lzip }, + { "lzma", archive_write_add_filter_lzma }, + { "lzop", archive_write_add_filter_lzop }, + { "uuencode", archive_write_add_filter_uuencode }, + { "xz", archive_write_add_filter_xz }, + { NULL, NULL } +}; + +int +archive_write_add_filter_by_name(struct archive *a, const char *name) +{ + int i; + + for (i = 0; names[i].name != NULL; i++) { + if (strcmp(name, names[i].name) == 0) + return ((names[i].setter)(a)); + } + + archive_set_error(a, EINVAL, "No such filter '%s'", name); + a->state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_bzip2.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_bzip2.c index 096a6a4c7..6526f5168 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_bzip2.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_bzip2.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,32 +55,18 @@ archive_write_set_compression_bzip2(struct archive *a) } #endif -#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) -int -archive_write_add_filter_bzip2(struct archive *a) -{ - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "bzip2 compression not supported on this platform"); - return (ARCHIVE_FATAL); -} -#else -/* Don't compile this if we don't have bzlib. */ - struct private_data { int compression_level; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) bz_stream stream; int64_t total_in; char *compressed; size_t compressed_buffer_size; +#else + struct archive_write_program_data *pdata; +#endif }; -/* - * Yuck. bzlib.h is not const-correct, so I need this one bit - * of ugly hackery to convert a const * pointer to a non-const pointer. - */ -#define SET_NEXT_IN(st,src) \ - (st)->stream.next_in = (char *)(uintptr_t)(const void *)(src) - static int archive_compressor_bzip2_close(struct archive_write_filter *); static int archive_compressor_bzip2_free(struct archive_write_filter *); static int archive_compressor_bzip2_open(struct archive_write_filter *); @@ -87,8 +74,6 @@ static int archive_compressor_bzip2_options(struct archive_write_filter *, const char *, const char *); static int archive_compressor_bzip2_write(struct archive_write_filter *, const void *, size_t); -static int drive_compressor(struct archive_write_filter *, - struct private_data *, int finishing); /* * Add a bzip2 compression filter to this write handle. @@ -115,11 +100,64 @@ archive_write_add_filter_bzip2(struct archive *_a) f->close = &archive_compressor_bzip2_close; f->free = &archive_compressor_bzip2_free; f->open = &archive_compressor_bzip2_open; - f->code = ARCHIVE_COMPRESSION_BZIP2; + f->code = ARCHIVE_FILTER_BZIP2; f->name = "bzip2"; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) return (ARCHIVE_OK); +#else + data->pdata = __archive_write_program_allocate(); + if (data->pdata == NULL) { + free(data); + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + data->compression_level = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Using external bzip2 program"); + return (ARCHIVE_WARN); +#endif +} + +/* + * Set write options. + */ +static int +archive_compressor_bzip2_options(struct archive_write_filter *f, + const char *key, const char *value) +{ + struct private_data *data = (struct private_data *)f->data; + + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->compression_level = value[0] - '0'; + /* Make '0' be a synonym for '1'. */ + /* This way, bzip2 compressor supports the same 0..9 + * range of levels as gzip. */ + if (data->compression_level < 1) + data->compression_level = 1; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +/* Don't compile this if we don't have bzlib. */ + +/* + * Yuck. bzlib.h is not const-correct, so I need this one bit + * of ugly hackery to convert a const * pointer to a non-const pointer. + */ +#define SET_NEXT_IN(st,src) \ + (st)->stream.next_in = (char *)(uintptr_t)(const void *)(src) +static int drive_compressor(struct archive_write_filter *, + struct private_data *, int finishing); + /* * Setup callback. */ @@ -133,10 +171,18 @@ archive_compressor_bzip2_open(struct archive_write_filter *f) if (ret != 0) return (ret); - /* TODO: Find a better way to size this. (Maybe look at the */ - /* block size expected by the following filter?) */ if (data->compressed == NULL) { - data->compressed_buffer_size = 65536; + size_t bs = 65536, bpb; + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + data->compressed_buffer_size = bs; data->compressed = (char *)malloc(data->compressed_buffer_size); if (data->compressed == NULL) { @@ -187,31 +233,6 @@ archive_compressor_bzip2_open(struct archive_write_filter *f) } /* - * Set write options. - */ -static int -archive_compressor_bzip2_options(struct archive_write_filter *f, - const char *key, const char *value) -{ - struct private_data *data = (struct private_data *)f->data; - - if (strcmp(key, "compression-level") == 0) { - if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || - value[1] != '\0') - return (ARCHIVE_WARN); - data->compression_level = value[0] - '0'; - /* Make '0' be a synonym for '1'. */ - /* This way, bzip2 compressor supports the same 0..9 - * range of levels as gzip. */ - if (data->compression_level < 1) - data->compression_level = 1; - return (ARCHIVE_OK); - } - - return (ARCHIVE_WARN); -} - -/* * Write data to the compressed stream. * * Returns ARCHIVE_OK if all data written, error otherwise. @@ -332,4 +353,55 @@ drive_compressor(struct archive_write_filter *f, } } +#else /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */ + +static int +archive_compressor_bzip2_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + struct archive_string as; + int r; + + archive_string_init(&as); + archive_strcpy(&as, "bzip2"); + + /* Specify compression level. */ + if (data->compression_level > 0) { + archive_strcat(&as, " -"); + archive_strappend_char(&as, '0' + data->compression_level); + } + f->write = archive_compressor_bzip2_write; + + r = __archive_write_program_open(f, data->pdata, as.s); + archive_string_free(&as); + return (r); +} + +static int +archive_compressor_bzip2_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_compressor_bzip2_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +static int +archive_compressor_bzip2_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + __archive_write_program_free(data->pdata); + free(data); + return (ARCHIVE_OK); +} + #endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */ diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_compress.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_compress.c index 465ff0e77..26fcef4d4 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_compress.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_compress.c @@ -135,7 +135,7 @@ archive_write_add_filter_compress(struct archive *_a) archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_add_filter_compress"); f->open = &archive_compressor_compress_open; - f->code = ARCHIVE_COMPRESSION_COMPRESS; + f->code = ARCHIVE_FILTER_COMPRESS; f->name = "compress"; return (ARCHIVE_OK); } @@ -148,8 +148,9 @@ archive_compressor_compress_open(struct archive_write_filter *f) { int ret; struct private_data *state; + size_t bs = 65536, bpb; - f->code = ARCHIVE_COMPRESSION_COMPRESS; + f->code = ARCHIVE_FILTER_COMPRESS; f->name = "compress"; ret = __archive_write_open_filter(f->next_filter); @@ -163,7 +164,16 @@ archive_compressor_compress_open(struct archive_write_filter *f) return (ARCHIVE_FATAL); } - state->compressed_buffer_size = 65536; + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + state->compressed_buffer_size = bs; state->compressed = malloc(state->compressed_buffer_size); if (state->compressed == NULL) { @@ -386,12 +396,12 @@ archive_compressor_compress_write(struct archive_write_filter *f, state->checkpoint = state->in_count + CHECK_GAP; - if (state->in_count <= 0x007fffff) - ratio = state->in_count * 256 / state->out_count; - else if ((ratio = state->out_count / 256) == 0) + if (state->in_count <= 0x007fffff && state->out_count != 0) + ratio = (int)(state->in_count * 256 / state->out_count); + else if ((ratio = (int)(state->out_count / 256)) == 0) ratio = 0x7fffffff; else - ratio = state->in_count / ratio; + ratio = (int)(state->in_count / ratio); if (ratio > state->compress_ratio) state->compress_ratio = ratio; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_grzip.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_grzip.c new file mode 100644 index 000000000..8dc287eae --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_grzip.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#include "archive.h" +#include "archive_write_private.h" + +struct write_grzip { + struct archive_write_program_data *pdata; +}; + +static int archive_write_grzip_open(struct archive_write_filter *); +static int archive_write_grzip_options(struct archive_write_filter *, + const char *, const char *); +static int archive_write_grzip_write(struct archive_write_filter *, + const void *, size_t); +static int archive_write_grzip_close(struct archive_write_filter *); +static int archive_write_grzip_free(struct archive_write_filter *); + +int +archive_write_add_filter_grzip(struct archive *_a) +{ + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct write_grzip *data; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_grzip"); + + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + data->pdata = __archive_write_program_allocate(); + if (data->pdata == NULL) { + free(data); + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + f->name = "grzip"; + f->code = ARCHIVE_FILTER_GRZIP; + f->data = data; + f->open = archive_write_grzip_open; + f->options = archive_write_grzip_options; + f->write = archive_write_grzip_write; + f->close = archive_write_grzip_close; + f->free = archive_write_grzip_free; + + /* Note: This filter always uses an external program, so we + * return "warn" to inform of the fact. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external grzip program for grzip compression"); + return (ARCHIVE_WARN); +} + +static int +archive_write_grzip_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + (void)f; /* UNUSED */ + (void)key; /* UNUSED */ + (void)value; /* UNUSED */ + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_grzip_open(struct archive_write_filter *f) +{ + struct write_grzip *data = (struct write_grzip *)f->data; + + return __archive_write_program_open(f, data->pdata, "grzip"); +} + +static int +archive_write_grzip_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct write_grzip *data = (struct write_grzip *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_write_grzip_close(struct archive_write_filter *f) +{ + struct write_grzip *data = (struct write_grzip *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +static int +archive_write_grzip_free(struct archive_write_filter *f) +{ + struct write_grzip *data = (struct write_grzip *)f->data; + + __archive_write_program_free(data->pdata); + free(data); + return (ARCHIVE_OK); +} diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c index d08ee265b..db18fd94a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_gzip.c 201 #include "archive.h" #include "archive_private.h" +#include "archive_string.h" #include "archive_write_private.h" #if ARCHIVE_VERSION_NUMBER < 4000000 @@ -54,24 +55,20 @@ archive_write_set_compression_gzip(struct archive *a) } #endif -#ifndef HAVE_ZLIB_H -int -archive_write_add_filter_gzip(struct archive *a) -{ - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "gzip compression not supported on this platform"); - return (ARCHIVE_FATAL); -} -#else /* Don't compile this if we don't have zlib. */ struct private_data { int compression_level; + int timestamp; +#ifdef HAVE_ZLIB_H z_stream stream; int64_t total_in; unsigned char *compressed; size_t compressed_buffer_size; unsigned long crc; +#else + struct archive_write_program_data *pdata; +#endif }; /* @@ -88,8 +85,10 @@ static int archive_compressor_gzip_write(struct archive_write_filter *, const void *, size_t); static int archive_compressor_gzip_close(struct archive_write_filter *); static int archive_compressor_gzip_free(struct archive_write_filter *); +#ifdef HAVE_ZLIB_H static int drive_compressor(struct archive_write_filter *, struct private_data *, int finishing); +#endif /* @@ -110,16 +109,72 @@ archive_write_add_filter_gzip(struct archive *_a) return (ARCHIVE_FATAL); } f->data = data; - data->compression_level = Z_DEFAULT_COMPRESSION; f->open = &archive_compressor_gzip_open; f->options = &archive_compressor_gzip_options; f->close = &archive_compressor_gzip_close; f->free = &archive_compressor_gzip_free; - f->code = ARCHIVE_COMPRESSION_GZIP; + f->code = ARCHIVE_FILTER_GZIP; f->name = "gzip"; +#ifdef HAVE_ZLIB_H + data->compression_level = Z_DEFAULT_COMPRESSION; return (ARCHIVE_OK); +#else + data->pdata = __archive_write_program_allocate(); + if (data->pdata == NULL) { + free(data); + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + data->compression_level = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Using external gzip program"); + return (ARCHIVE_WARN); +#endif } +static int +archive_compressor_gzip_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + +#ifdef HAVE_ZLIB_H + free(data->compressed); +#else + __archive_write_program_free(data->pdata); +#endif + free(data); + f->data = NULL; + return (ARCHIVE_OK); +} + +/* + * Set write options. + */ +static int +archive_compressor_gzip_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct private_data *data = (struct private_data *)f->data; + + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->compression_level = value[0] - '0'; + return (ARCHIVE_OK); + } + if (strcmp(key, "timestamp") == 0) { + data->timestamp = (value == NULL)?-1:1; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +#ifdef HAVE_ZLIB_H /* * Setup callback. */ @@ -128,14 +183,23 @@ archive_compressor_gzip_open(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; int ret; - time_t t; ret = __archive_write_open_filter(f->next_filter); if (ret != ARCHIVE_OK) return (ret); if (data->compressed == NULL) { - data->compressed_buffer_size = 65536; + size_t bs = 65536, bpb; + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of + * the of bytes per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + data->compressed_buffer_size = bs; data->compressed = (unsigned char *)malloc(data->compressed_buffer_size); if (data->compressed == NULL) { @@ -147,18 +211,21 @@ archive_compressor_gzip_open(struct archive_write_filter *f) data->crc = crc32(0L, NULL, 0); data->stream.next_out = data->compressed; - data->stream.avail_out = data->compressed_buffer_size; + data->stream.avail_out = (uInt)data->compressed_buffer_size; /* Prime output buffer with a gzip header. */ - t = time(NULL); data->compressed[0] = 0x1f; /* GZip signature bytes */ data->compressed[1] = 0x8b; data->compressed[2] = 0x08; /* "Deflate" compression */ data->compressed[3] = 0; /* No options */ - data->compressed[4] = (t)&0xff; /* Timestamp */ - data->compressed[5] = (t>>8)&0xff; - data->compressed[6] = (t>>16)&0xff; - data->compressed[7] = (t>>24)&0xff; + if (data->timestamp >= 0) { + time_t t = time(NULL); + data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */ + data->compressed[5] = (uint8_t)(t>>8)&0xff; + data->compressed[6] = (uint8_t)(t>>16)&0xff; + data->compressed[7] = (uint8_t)(t>>24)&0xff; + } else + memset(&data->compressed[4], 0, 4); data->compressed[8] = 0; /* No deflate options */ data->compressed[9] = 3; /* OS=Unix */ data->stream.next_out += 10; @@ -191,8 +258,8 @@ archive_compressor_gzip_open(struct archive_write_filter *f) "compression library: invalid setup parameter"); break; case Z_MEM_ERROR: - archive_set_error(f->archive, ENOMEM, "Internal error initializing " - "compression library"); + archive_set_error(f->archive, ENOMEM, + "Internal error initializing compression library"); break; case Z_VERSION_ERROR: archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, @@ -205,25 +272,6 @@ archive_compressor_gzip_open(struct archive_write_filter *f) } /* - * Set write options. - */ -static int -archive_compressor_gzip_options(struct archive_write_filter *f, const char *key, - const char *value) -{ - struct private_data *data = (struct private_data *)f->data; - - if (strcmp(key, "compression-level") == 0) { - if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || - value[1] != '\0') - return (ARCHIVE_WARN); - data->compression_level = value[0] - '0'; - return (ARCHIVE_OK); - } - return (ARCHIVE_WARN); -} - -/* * Write data to the compressed stream. */ static int @@ -234,12 +282,12 @@ archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff, int ret; /* Update statistics */ - data->crc = crc32(data->crc, (const Bytef *)buff, length); + data->crc = crc32(data->crc, (const Bytef *)buff, (uInt)length); data->total_in += length; /* Compress input data to output buffer */ SET_NEXT_IN(data, buff); - data->stream.avail_in = length; + data->stream.avail_in = (uInt)length; if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK) return (ret); @@ -266,14 +314,14 @@ archive_compressor_gzip_close(struct archive_write_filter *f) } if (ret == ARCHIVE_OK) { /* Build and write out 8-byte trailer. */ - trailer[0] = (data->crc)&0xff; - trailer[1] = (data->crc >> 8)&0xff; - trailer[2] = (data->crc >> 16)&0xff; - trailer[3] = (data->crc >> 24)&0xff; - trailer[4] = (data->total_in)&0xff; - trailer[5] = (data->total_in >> 8)&0xff; - trailer[6] = (data->total_in >> 16)&0xff; - trailer[7] = (data->total_in >> 24)&0xff; + trailer[0] = (uint8_t)(data->crc)&0xff; + trailer[1] = (uint8_t)(data->crc >> 8)&0xff; + trailer[2] = (uint8_t)(data->crc >> 16)&0xff; + trailer[3] = (uint8_t)(data->crc >> 24)&0xff; + trailer[4] = (uint8_t)(data->total_in)&0xff; + trailer[5] = (uint8_t)(data->total_in >> 8)&0xff; + trailer[6] = (uint8_t)(data->total_in >> 16)&0xff; + trailer[7] = (uint8_t)(data->total_in >> 24)&0xff; ret = __archive_write_filter(f->next_filter, trailer, 8); } @@ -289,16 +337,6 @@ archive_compressor_gzip_close(struct archive_write_filter *f) return (r1 < ret ? r1 : ret); } -static int -archive_compressor_gzip_free(struct archive_write_filter *f) -{ - struct private_data *data = (struct private_data *)f->data; - free(data->compressed); - free(data); - f->data = NULL; - return (ARCHIVE_OK); -} - /* * Utility function to push input data through compressor, * writing full output blocks as necessary. @@ -320,7 +358,8 @@ drive_compressor(struct archive_write_filter *f, if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); data->stream.next_out = data->compressed; - data->stream.avail_out = data->compressed_buffer_size; + data->stream.avail_out = + (uInt)data->compressed_buffer_size; } /* If there's nothing to do, we're done. */ @@ -353,4 +392,51 @@ drive_compressor(struct archive_write_filter *f, } } +#else /* HAVE_ZLIB_H */ + +static int +archive_compressor_gzip_open(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + struct archive_string as; + int r; + + archive_string_init(&as); + archive_strcpy(&as, "gzip"); + + /* Specify compression level. */ + if (data->compression_level > 0) { + archive_strcat(&as, " -"); + archive_strappend_char(&as, '0' + data->compression_level); + } + if (data->timestamp < 0) + /* Do not save timestamp. */ + archive_strcat(&as, " -n"); + else if (data->timestamp > 0) + /* Save timestamp. */ + archive_strcat(&as, " -N"); + + f->write = archive_compressor_gzip_write; + r = __archive_write_program_open(f, data->pdata, as.s); + archive_string_free(&as); + return (r); +} + +static int +archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_compressor_gzip_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + #endif /* HAVE_ZLIB_H */ diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lrzip.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lrzip.c new file mode 100644 index 000000000..85fdf6af5 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lrzip.c @@ -0,0 +1,192 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include "archive.h" +#include "archive_string.h" +#include "archive_write_private.h" + +struct write_lrzip { + struct archive_write_program_data *pdata; + int compression_level; + enum { lzma = 0, bzip2, gzip, lzo, zpaq } compression; +}; + +static int archive_write_lrzip_open(struct archive_write_filter *); +static int archive_write_lrzip_options(struct archive_write_filter *, + const char *, const char *); +static int archive_write_lrzip_write(struct archive_write_filter *, + const void *, size_t); +static int archive_write_lrzip_close(struct archive_write_filter *); +static int archive_write_lrzip_free(struct archive_write_filter *); + +int +archive_write_add_filter_lrzip(struct archive *_a) +{ + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct write_lrzip *data; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_lrzip"); + + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + data->pdata = __archive_write_program_allocate(); + if (data->pdata == NULL) { + free(data); + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + f->name = "lrzip"; + f->code = ARCHIVE_FILTER_LRZIP; + f->data = data; + f->open = archive_write_lrzip_open; + f->options = archive_write_lrzip_options; + f->write = archive_write_lrzip_write; + f->close = archive_write_lrzip_close; + f->free = archive_write_lrzip_free; + + /* Note: This filter always uses an external program, so we + * return "warn" to inform of the fact. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lrzip program for lrzip compression"); + return (ARCHIVE_WARN); +} + +static int +archive_write_lrzip_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct write_lrzip *data = (struct write_lrzip *)f->data; + + if (strcmp(key, "compression") == 0) { + if (value == NULL) + return (ARCHIVE_WARN); + else if (strcmp(value, "bzip2") == 0) + data->compression = bzip2; + else if (strcmp(value, "gzip") == 0) + data->compression = gzip; + else if (strcmp(value, "lzo") == 0) + data->compression = lzo; + else if (strcmp(value, "zpaq") == 0) + data->compression = zpaq; + else + return (ARCHIVE_WARN); + return (ARCHIVE_OK); + } else if (strcmp(key, "compression-level") == 0) { + if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->compression_level = value[0] - '0'; + return (ARCHIVE_OK); + } + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_lrzip_open(struct archive_write_filter *f) +{ + struct write_lrzip *data = (struct write_lrzip *)f->data; + struct archive_string as; + int r; + + archive_string_init(&as); + archive_strcpy(&as, "lrzip -q"); + + /* Specify compression type. */ + switch (data->compression) { + case lzma:/* default compression */ + break; + case bzip2: + archive_strcat(&as, " -b"); + break; + case gzip: + archive_strcat(&as, " -g"); + break; + case lzo: + archive_strcat(&as, " -l"); + break; + case zpaq: + archive_strcat(&as, " -z"); + break; + } + + /* Specify compression level. */ + if (data->compression_level > 0) { + archive_strcat(&as, " -L "); + archive_strappend_char(&as, '0' + data->compression_level); + } + + r = __archive_write_program_open(f, data->pdata, as.s); + archive_string_free(&as); + return (r); +} + +static int +archive_write_lrzip_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct write_lrzip *data = (struct write_lrzip *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_write_lrzip_close(struct archive_write_filter *f) +{ + struct write_lrzip *data = (struct write_lrzip *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +static int +archive_write_lrzip_free(struct archive_write_filter *f) +{ + struct write_lrzip *data = (struct write_lrzip *)f->data; + + __archive_write_program_free(data->pdata); + free(data); + return (ARCHIVE_OK); +} diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lzop.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lzop.c new file mode 100644 index 000000000..088ecea51 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lzop.c @@ -0,0 +1,486 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); +//#undef HAVE_LZO_LZOCONF_H +//#undef HAVE_LZO_LZO1X_H + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#include <time.h> +#ifdef HAVE_LZO_LZOCONF_H +#include <lzo/lzoconf.h> +#endif +#ifdef HAVE_LZO_LZO1X_H +#include <lzo/lzo1x.h> +#endif + +#include "archive.h" +#include "archive_string.h" +#include "archive_endian.h" +#include "archive_write_private.h" + +enum lzo_method { + METHOD_LZO1X_1 = 1, + METHOD_LZO1X_1_15 = 2, + METHOD_LZO1X_999 = 3 +}; +struct write_lzop { + int compression_level; +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) + unsigned char *uncompressed; + size_t uncompressed_buffer_size; + size_t uncompressed_avail_bytes; + unsigned char *compressed; + size_t compressed_buffer_size; + enum lzo_method method; + unsigned char level; + lzo_voidp work_buffer; + lzo_uint32 work_buffer_size; + char header_written; +#else + struct archive_write_program_data *pdata; +#endif +}; + +static int archive_write_lzop_open(struct archive_write_filter *); +static int archive_write_lzop_options(struct archive_write_filter *, + const char *, const char *); +static int archive_write_lzop_write(struct archive_write_filter *, + const void *, size_t); +static int archive_write_lzop_close(struct archive_write_filter *); +static int archive_write_lzop_free(struct archive_write_filter *); + +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +/* Maximum block size. */ +#define BLOCK_SIZE (256 * 1024) +/* Block infomation is composed of uncompressed size(4 bytes), + * compressed size(4 bytes) and the checksum of uncompressed data(4 bytes) + * in this lzop writer. */ +#define BLOCK_INfO_SIZE 12 + +#define HEADER_VERSION 9 +#define HEADER_LIBVERSION 11 +#define HEADER_METHOD 15 +#define HEADER_LEVEL 16 +#define HEADER_MTIME_LOW 25 +#define HEADER_MTIME_HIGH 29 +#define HEADER_H_CHECKSUM 34 + +/* + * Header template. + */ +static const unsigned char header[] = { + /* LZOP Magic code 9 bytes */ + 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a, + /* LZOP utility version(fake data) 2 bytes */ + 0x10, 0x30, + /* LZO library version 2 bytes */ + 0x09, 0x40, + /* Minimum required LZO library version 2 bytes */ + 0x09, 0x40, + /* Method */ + 1, + /* Level */ + 5, + /* Flags 4 bytes + * -OS Unix + * -Stdout + * -Stdin + * -Adler32 used for uncompressed data 4 bytes */ + 0x03, 0x00, 0x00, 0x0d, + /* Mode (AE_IFREG | 0644) 4 bytes */ + 0x00, 0x00, 0x81, 0xa4, + /* Mtime low 4 bytes */ + 0x00, 0x00, 0x00, 0x00, + /* Mtime high 4 bytes */ + 0x00, 0x00, 0x00, 0x00, + /* Filename length */ + 0x00, + /* Header checksum 4 bytes */ + 0x00, 0x00, 0x00, 0x00, +}; +#endif + +int +archive_write_add_filter_lzop(struct archive *_a) +{ + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct write_lzop *data; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_lzop"); + + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + f->name = "lzop"; + f->code = ARCHIVE_FILTER_LZOP; + f->data = data; + f->open = archive_write_lzop_open; + f->options = archive_write_lzop_options; + f->write = archive_write_lzop_write; + f->close = archive_write_lzop_close; + f->free = archive_write_lzop_free; +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) + if (lzo_init() != LZO_E_OK) { + free(data); + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "lzo_init(type check) failed"); + return (ARCHIVE_FATAL); + } + if (lzo_version() < 0x940) { + free(data); + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "liblzo library is too old(%s < 0.940)", + lzo_version_string()); + return (ARCHIVE_FATAL); + } + data->compression_level = 5; + return (ARCHIVE_OK); +#else + data->pdata = __archive_write_program_allocate(); + if (data->pdata == NULL) { + free(data); + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + data->compression_level = 0; + /* Note: We return "warn" to inform of using an external lzop + * program. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lzop program for lzop compression"); + return (ARCHIVE_WARN); +#endif +} + +static int +archive_write_lzop_free(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) + free(data->uncompressed); + free(data->compressed); + free(data->work_buffer); +#else + __archive_write_program_free(data->pdata); +#endif + free(data); + return (ARCHIVE_OK); +} + +static int +archive_write_lzop_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || !(value[0] >= '1' && value[0] <= '9') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->compression_level = value[0] - '0'; + return (ARCHIVE_OK); + } + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +static int +archive_write_lzop_open(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + int ret; + + ret = __archive_write_open_filter(f->next_filter); + if (ret != ARCHIVE_OK) + return (ret); + + switch (data->compression_level) { + case 1: + data->method = METHOD_LZO1X_1_15; data->level = 1; break; + default: + case 2: case 3: case 4: case 5: case 6: + data->method = METHOD_LZO1X_1; data->level = 5; break; + case 7: + data->method = METHOD_LZO1X_999; data->level = 7; break; + case 8: + data->method = METHOD_LZO1X_999; data->level = 8; break; + case 9: + data->method = METHOD_LZO1X_999; data->level = 9; break; + } + switch (data->method) { + case METHOD_LZO1X_1: + data->work_buffer_size = LZO1X_1_MEM_COMPRESS; break; + case METHOD_LZO1X_1_15: + data->work_buffer_size = LZO1X_1_15_MEM_COMPRESS; break; + case METHOD_LZO1X_999: + data->work_buffer_size = LZO1X_999_MEM_COMPRESS; break; + } + if (data->work_buffer == NULL) { + data->work_buffer = (lzo_voidp)malloc(data->work_buffer_size); + if (data->work_buffer == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + } + if (data->compressed == NULL) { + data->compressed_buffer_size = sizeof(header) + + BLOCK_SIZE + (BLOCK_SIZE >> 4) + 64 + 3; + data->compressed = (unsigned char *) + malloc(data->compressed_buffer_size); + if (data->compressed == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + } + if (data->uncompressed == NULL) { + data->uncompressed_buffer_size = BLOCK_SIZE; + data->uncompressed = (unsigned char *) + malloc(data->uncompressed_buffer_size); + if (data->uncompressed == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + data->uncompressed_avail_bytes = BLOCK_SIZE; + } + return (ARCHIVE_OK); +} + +static int +make_header(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + int64_t t; + uint32_t checksum; + + memcpy(data->compressed, header, sizeof(header)); + /* Overwrite library version. */ + data->compressed[HEADER_LIBVERSION] = (unsigned char ) + (lzo_version() >> 8) & 0xff; + data->compressed[HEADER_LIBVERSION + 1] = (unsigned char ) + lzo_version() & 0xff; + /* Overwrite method and level. */ + data->compressed[HEADER_METHOD] = (unsigned char)data->method; + data->compressed[HEADER_LEVEL] = data->level; + /* Overwrite mtime with current time. */ + t = (int64_t)time(NULL); + archive_be32enc(&data->compressed[HEADER_MTIME_LOW], + (uint32_t)(t & 0xffffffff)); + archive_be32enc(&data->compressed[HEADER_MTIME_HIGH], + (uint32_t)((t >> 32) & 0xffffffff)); + /* Overwrite header checksum with calculated value. */ + checksum = lzo_adler32(1, data->compressed + HEADER_VERSION, + (lzo_uint)(HEADER_H_CHECKSUM - HEADER_VERSION)); + archive_be32enc(&data->compressed[HEADER_H_CHECKSUM], checksum); + return (sizeof(header)); +} + +static int +drive_compressor(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + unsigned char *p; + const int block_info_bytes = 12; + int header_bytes, r; + lzo_uint usize, csize; + uint32_t checksum; + + if (!data->header_written) { + header_bytes = make_header(f); + data->header_written = 1; + } else + header_bytes = 0; + p = data->compressed; + + usize = (lzo_uint) + (data->uncompressed_buffer_size - data->uncompressed_avail_bytes); + csize = 0; + switch (data->method) { + default: + case METHOD_LZO1X_1: + r = lzo1x_1_compress(data->uncompressed, usize, + p + header_bytes + block_info_bytes, &csize, + data->work_buffer); + break; + case METHOD_LZO1X_1_15: + r = lzo1x_1_15_compress(data->uncompressed, usize, + p + header_bytes + block_info_bytes, &csize, + data->work_buffer); + break; + case METHOD_LZO1X_999: + r = lzo1x_999_compress_level(data->uncompressed, usize, + p + header_bytes + block_info_bytes, &csize, + data->work_buffer, NULL, 0, 0, data->level); + break; + } + if (r != LZO_E_OK) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Lzop compression failed: returned status %d", r); + return (ARCHIVE_FATAL); + } + + /* Store uncompressed size. */ + archive_be32enc(p + header_bytes, (uint32_t)usize); + /* Store the checksum of the uncompressed data. */ + checksum = lzo_adler32(1, data->uncompressed, usize); + archive_be32enc(p + header_bytes + 8, checksum); + + if (csize < usize) { + /* Store compressed size. */ + archive_be32enc(p + header_bytes + 4, (uint32_t)csize); + r = __archive_write_filter(f->next_filter, data->compressed, + header_bytes + block_info_bytes + csize); + } else { + /* + * This case, we output uncompressed data instead. + */ + /* Store uncompressed size as compressed size. */ + archive_be32enc(p + header_bytes + 4, (uint32_t)usize); + r = __archive_write_filter(f->next_filter, data->compressed, + header_bytes + block_info_bytes); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + r = __archive_write_filter(f->next_filter, data->uncompressed, + usize); + } + + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); +} + +static int +archive_write_lzop_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + const char *p = buff; + int r; + + do { + if (data->uncompressed_avail_bytes > length) { + memcpy(data->uncompressed + + data->uncompressed_buffer_size + - data->uncompressed_avail_bytes, + p, length); + data->uncompressed_avail_bytes -= length; + return (ARCHIVE_OK); + } + + memcpy(data->uncompressed + data->uncompressed_buffer_size + - data->uncompressed_avail_bytes, + p, data->uncompressed_avail_bytes); + length -= data->uncompressed_avail_bytes; + p += data->uncompressed_avail_bytes; + data->uncompressed_avail_bytes = 0; + + r = drive_compressor(f); + if (r != ARCHIVE_OK) return (r); + data->uncompressed_avail_bytes = BLOCK_SIZE; + } while (length); + + return (ARCHIVE_OK); +} + +static int +archive_write_lzop_close(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + const uint32_t endmark = 0; + int r; + + if (data->uncompressed_avail_bytes < BLOCK_SIZE) { + /* Compress and output remaining data. */ + r = drive_compressor(f); + if (r != ARCHIVE_OK) + return (r); + } + /* Write a zero uncompressed size as the end mark of the series of + * compressed block. */ + r = __archive_write_filter(f->next_filter, &endmark, sizeof(endmark)); + if (r != ARCHIVE_OK) + return (r); + return (__archive_write_close_filter(f->next_filter)); +} + +#else +static int +archive_write_lzop_open(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + struct archive_string as; + int r; + + archive_string_init(&as); + archive_strcpy(&as, "lzop"); + /* Specify compression level. */ + if (data->compression_level > 0) { + archive_strappend_char(&as, ' '); + archive_strappend_char(&as, '-'); + archive_strappend_char(&as, '0' + data->compression_level); + } + + r = __archive_write_program_open(f, data->pdata, as.s); + archive_string_free(&as); + return (r); +} + +static int +archive_write_lzop_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_write_lzop_close(struct archive_write_filter *f) +{ + struct write_lzop *data = (struct write_lzop *)f->data; + + return __archive_write_program_close(f, data->pdata); +} +#endif diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c index 3dcc9df7b..fc232da0c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2007 Joerg Sonnenberger + * Copyright (c) 2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +45,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_program.c #include "archive.h" #include "archive_private.h" +#include "archive_string.h" #include "archive_write_private.h" +#include "filter_fork.h" #if ARCHIVE_VERSION_NUMBER < 4000000 int @@ -55,36 +58,24 @@ archive_write_set_compression_program(struct archive *a, const char *cmd) } #endif -/* This capability is only available on POSIX systems. */ -#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \ - !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__)) - -/* - * On non-Posix systems, allow the program to build, but choke if - * this function is actually invoked. - */ -int -archive_write_add_filter_program(struct archive *_a, const char *cmd) -{ - archive_set_error(_a, -1, - "External compression programs not supported on this platform"); - return (ARCHIVE_FATAL); -} - +struct archive_write_program_data { +#if defined(_WIN32) && !defined(__CYGWIN__) + HANDLE child; #else - -#include "filter_fork.h" - -struct private_data { - char *cmd; - char *description; pid_t child; +#endif int child_stdin, child_stdout; char *child_buf; size_t child_buf_len, child_buf_avail; }; +struct private_data { + struct archive_write_program_data *pdata; + struct archive_string description; + char *cmd; +}; + static int archive_compressor_program_open(struct archive_write_filter *); static int archive_compressor_program_write(struct archive_write_filter *, const void *, size_t); @@ -99,35 +90,125 @@ int archive_write_add_filter_program(struct archive *_a, const char *cmd) { struct archive_write_filter *f = __archive_write_allocate_filter(_a); - struct archive_write *a = (struct archive_write *)_a; struct private_data *data; static const char *prefix = "Program: "; - archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_add_filter_program"); - data = calloc(1, sizeof(*data)); - if (data == NULL) { - archive_set_error(&a->archive, ENOMEM, "Out of memory"); - return (ARCHIVE_FATAL); - } + + f->data = calloc(1, sizeof(*data)); + if (f->data == NULL) + goto memerr; + data = (struct private_data *)f->data; + data->cmd = strdup(cmd); - data->description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1); - strcpy(data->description, prefix); - strcat(data->description, cmd); - - f->name = data->description; - f->data = data; - f->open = &archive_compressor_program_open; - f->code = ARCHIVE_COMPRESSION_PROGRAM; + if (data->cmd == NULL) + goto memerr; + + data->pdata = __archive_write_program_allocate(); + if (data->pdata == NULL) + goto memerr; + + /* Make up a description string. */ + if (archive_string_ensure(&data->description, + strlen(prefix) + strlen(cmd) + 1) == NULL) + goto memerr; + archive_strcpy(&data->description, prefix); + archive_strcat(&data->description, cmd); + + f->name = data->description.s; + f->code = ARCHIVE_FILTER_PROGRAM; + f->open = archive_compressor_program_open; + f->write = archive_compressor_program_write; + f->close = archive_compressor_program_close; + f->free = archive_compressor_program_free; return (ARCHIVE_OK); +memerr: + archive_compressor_program_free(f); + archive_set_error(_a, ENOMEM, + "Can't allocate memory for filter program"); + return (ARCHIVE_FATAL); } -/* - * Setup callback. - */ static int archive_compressor_program_open(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_open(f, data->pdata, data->cmd); +} + +static int +archive_compressor_program_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_write(f, data->pdata, buff, length); +} + +static int +archive_compressor_program_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + return __archive_write_program_close(f, data->pdata); +} + +static int +archive_compressor_program_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + + if (data) { + free(data->cmd); + archive_string_free(&data->description); + __archive_write_program_free(data->pdata); + free(data); + f->data = NULL; + } + return (ARCHIVE_OK); +} + +/* + * Allocate resources for executing an external program. + */ +struct archive_write_program_data * +__archive_write_program_allocate(void) +{ + struct archive_write_program_data *data; + + data = calloc(1, sizeof(struct archive_write_program_data)); + if (data == NULL) + return (data); + data->child_stdin = -1; + data->child_stdout = -1; + return (data); +} + +/* + * Release the resources. + */ +int +__archive_write_program_free(struct archive_write_program_data *data) +{ + + if (data) { +#if defined(_WIN32) && !defined(__CYGWIN__) + if (data->child) + CloseHandle(data->child); +#endif + free(data->child_buf); + free(data); + } + return (ARCHIVE_OK); +} + +int +__archive_write_program_open(struct archive_write_filter *f, + struct archive_write_program_data *data, const char *cmd) +{ + pid_t child; int ret; ret = __archive_write_open_filter(f->next_filter); @@ -146,23 +227,34 @@ archive_compressor_program_open(struct archive_write_filter *f) } } - if ((data->child = __archive_create_child(data->cmd, - &data->child_stdin, &data->child_stdout)) == -1) { + child = __archive_create_child(cmd, &data->child_stdin, + &data->child_stdout); + if (child == -1) { archive_set_error(f->archive, EINVAL, "Can't initialise filter"); return (ARCHIVE_FATAL); } - - f->write = archive_compressor_program_write; - f->close = archive_compressor_program_close; - f->free = archive_compressor_program_free; - return (0); +#if defined(_WIN32) && !defined(__CYGWIN__) + data->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child); + if (data->child == NULL) { + close(data->child_stdin); + data->child_stdin = -1; + close(data->child_stdout); + data->child_stdout = -1; + archive_set_error(f->archive, EINVAL, + "Can't initialise filter"); + return (ARCHIVE_FATAL); + } +#else + data->child = child; +#endif + return (ARCHIVE_OK); } static ssize_t -child_write(struct archive_write_filter *f, const char *buf, size_t buf_len) +child_write(struct archive_write_filter *f, + struct archive_write_program_data *data, const char *buf, size_t buf_len) { - struct private_data *data = f->data; ssize_t ret; if (data->child_stdin == -1) @@ -171,75 +263,75 @@ child_write(struct archive_write_filter *f, const char *buf, size_t buf_len) if (buf_len == 0) return (-1); -restart_write: - do { - ret = write(data->child_stdin, buf, buf_len); - } while (ret == -1 && errno == EINTR); - - if (ret > 0) - return (ret); - if (ret == 0) { - close(data->child_stdin); - data->child_stdin = -1; - fcntl(data->child_stdout, F_SETFL, 0); - return (0); - } - if (ret == -1 && errno != EAGAIN) - return (-1); - - if (data->child_stdout == -1) { - fcntl(data->child_stdin, F_SETFL, 0); - __archive_check_child(data->child_stdin, data->child_stdout); - goto restart_write; - } - - do { - ret = read(data->child_stdout, - data->child_buf + data->child_buf_avail, - data->child_buf_len - data->child_buf_avail); - } while (ret == -1 && errno == EINTR); + for (;;) { + do { + ret = write(data->child_stdin, buf, buf_len); + } while (ret == -1 && errno == EINTR); + + if (ret > 0) + return (ret); + if (ret == 0) { + close(data->child_stdin); + data->child_stdin = -1; + fcntl(data->child_stdout, F_SETFL, 0); + return (0); + } + if (ret == -1 && errno != EAGAIN) + return (-1); + + if (data->child_stdout == -1) { + fcntl(data->child_stdin, F_SETFL, 0); + __archive_check_child(data->child_stdin, + data->child_stdout); + continue; + } - if (ret == 0 || (ret == -1 && errno == EPIPE)) { - close(data->child_stdout); - data->child_stdout = -1; - fcntl(data->child_stdin, F_SETFL, 0); - goto restart_write; - } - if (ret == -1 && errno == EAGAIN) { - __archive_check_child(data->child_stdin, data->child_stdout); - goto restart_write; - } - if (ret == -1) - return (-1); + do { + ret = read(data->child_stdout, + data->child_buf + data->child_buf_avail, + data->child_buf_len - data->child_buf_avail); + } while (ret == -1 && errno == EINTR); - data->child_buf_avail += ret; + if (ret == 0 || (ret == -1 && errno == EPIPE)) { + close(data->child_stdout); + data->child_stdout = -1; + fcntl(data->child_stdin, F_SETFL, 0); + continue; + } + if (ret == -1 && errno == EAGAIN) { + __archive_check_child(data->child_stdin, + data->child_stdout); + continue; + } + if (ret == -1) + return (-1); - ret = __archive_write_filter(f->next_filter, - data->child_buf, data->child_buf_avail); - if (ret <= 0) - return (-1); + data->child_buf_avail += ret; - if ((size_t)ret < data->child_buf_avail) { - memmove(data->child_buf, data->child_buf + ret, - data->child_buf_avail - ret); + ret = __archive_write_filter(f->next_filter, + data->child_buf, data->child_buf_avail); + if (ret != ARCHIVE_OK) + return (-1); + data->child_buf_avail = 0; } - data->child_buf_avail -= ret; - goto restart_write; } /* - * Write data to the compressed stream. + * Write data to the filter stream. */ -static int -archive_compressor_program_write(struct archive_write_filter *f, - const void *buff, size_t length) +int +__archive_write_program_write(struct archive_write_filter *f, + struct archive_write_program_data *data, const void *buff, size_t length) { ssize_t ret; const char *buf; + if (data->child == 0) + return (ARCHIVE_OK); + buf = buff; while (length > 0) { - ret = child_write(f, buf, length); + ret = child_write(f, data, buf, length); if (ret == -1 || ret == 0) { archive_set_error(f->archive, EIO, "Can't write to filter"); @@ -251,17 +343,19 @@ archive_compressor_program_write(struct archive_write_filter *f, return (ARCHIVE_OK); } - /* - * Finish the compression... + * Finish the filtering... */ -static int -archive_compressor_program_close(struct archive_write_filter *f) +int +__archive_write_program_close(struct archive_write_filter *f, + struct archive_write_program_data *data) { - struct private_data *data = (struct private_data *)f->data; int ret, r1, status; ssize_t bytes_read; + if (data->child == 0) + return __archive_write_close_filter(f->next_filter); + ret = 0; close(data->child_stdin); data->child_stdin = -1; @@ -302,6 +396,10 @@ cleanup: close(data->child_stdout); while (waitpid(data->child, &status, 0) == -1 && errno == EINTR) continue; +#if defined(_WIN32) && !defined(__CYGWIN__) + CloseHandle(data->child); +#endif + data->child = 0; if (status != 0) { archive_set_error(f->archive, EIO, @@ -312,16 +410,3 @@ cleanup: return (r1 < ret ? r1 : ret); } -static int -archive_compressor_program_free(struct archive_write_filter *f) -{ - struct private_data *data = (struct private_data *)f->data; - free(data->cmd); - free(data->description); - free(data->child_buf); - free(data); - f->data = NULL; - return (ARCHIVE_OK); -} - -#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */ diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_uuencode.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_uuencode.c new file mode 100644 index 000000000..23d9c150d --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_uuencode.c @@ -0,0 +1,305 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" +#include "archive_write_private.h" + +#define LBYTES 45 + +struct private_uuencode { + int mode; + struct archive_string name; + struct archive_string encoded_buff; + size_t bs; + size_t hold_len; + unsigned char hold[LBYTES]; +}; + +static int archive_filter_uuencode_options(struct archive_write_filter *, + const char *, const char *); +static int archive_filter_uuencode_open(struct archive_write_filter *); +static int archive_filter_uuencode_write(struct archive_write_filter *, + const void *, size_t); +static int archive_filter_uuencode_close(struct archive_write_filter *); +static int archive_filter_uuencode_free(struct archive_write_filter *); +static void uu_encode(struct archive_string *, const unsigned char *, size_t); +static int64_t atol8(const char *, size_t); + +/* + * Add a compress filter to this write handle. + */ +int +archive_write_add_filter_uuencode(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct archive_write_filter *f = __archive_write_allocate_filter(_a); + struct private_uuencode *state; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_uu"); + + state = (struct private_uuencode *)calloc(1, sizeof(*state)); + if (state == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for uuencode filter"); + return (ARCHIVE_FATAL); + } + archive_strcpy(&state->name, "-"); + state->mode = 0644; + + f->data = state; + f->name = "uuencode"; + f->code = ARCHIVE_FILTER_UU; + f->open = archive_filter_uuencode_open; + f->options = archive_filter_uuencode_options; + f->write = archive_filter_uuencode_write; + f->close = archive_filter_uuencode_close; + f->free = archive_filter_uuencode_free; + + return (ARCHIVE_OK); +} + +/* + * Set write options. + */ +static int +archive_filter_uuencode_options(struct archive_write_filter *f, const char *key, + const char *value) +{ + struct private_uuencode *state = (struct private_uuencode *)f->data; + + if (strcmp(key, "mode") == 0) { + if (value == NULL) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "mode option requires octal digits"); + return (ARCHIVE_FAILED); + } + state->mode = (int)atol8(value, strlen(value)) & 0777; + return (ARCHIVE_OK); + } else if (strcmp(key, "name") == 0) { + if (value == NULL) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "name option requires a string"); + return (ARCHIVE_FAILED); + } + archive_strcpy(&state->name, value); + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +/* + * Setup callback. + */ +static int +archive_filter_uuencode_open(struct archive_write_filter *f) +{ + struct private_uuencode *state = (struct private_uuencode *)f->data; + size_t bs = 65536, bpb; + int ret; + + ret = __archive_write_open_filter(f->next_filter); + if (ret != ARCHIVE_OK) + return (ret); + + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + + state->bs = bs; + if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for uuencode buffer"); + return (ARCHIVE_FATAL); + } + + archive_string_sprintf(&state->encoded_buff, "begin %o %s\n", + state->mode, state->name.s); + + f->data = state; + return (0); +} + +static void +uu_encode(struct archive_string *as, const unsigned char *p, size_t len) +{ + int c; + + c = (int)len; + archive_strappend_char(as, c?c + 0x20:'`'); + for (; len >= 3; p += 3, len -= 3) { + c = p[0] >> 2; + archive_strappend_char(as, c?c + 0x20:'`'); + c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4); + archive_strappend_char(as, c?c + 0x20:'`'); + c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6); + archive_strappend_char(as, c?c + 0x20:'`'); + c = p[2] & 0x3f; + archive_strappend_char(as, c?c + 0x20:'`'); + } + if (len > 0) { + c = p[0] >> 2; + archive_strappend_char(as, c?c + 0x20:'`'); + c = (p[0] & 0x03) << 4; + if (len == 1) { + archive_strappend_char(as, c?c + 0x20:'`'); + archive_strappend_char(as, '`'); + archive_strappend_char(as, '`'); + } else { + c |= (p[1] & 0xf0) >> 4; + archive_strappend_char(as, c?c + 0x20:'`'); + c = (p[1] & 0x0f) << 2; + archive_strappend_char(as, c?c + 0x20:'`'); + archive_strappend_char(as, '`'); + } + } + archive_strappend_char(as, '\n'); +} + +/* + * Write data to the encoded stream. + */ +static int +archive_filter_uuencode_write(struct archive_write_filter *f, const void *buff, + size_t length) +{ + struct private_uuencode *state = (struct private_uuencode *)f->data; + const unsigned char *p = buff; + int ret = ARCHIVE_OK; + + if (length == 0) + return (ret); + + if (state->hold_len) { + while (state->hold_len < LBYTES && length > 0) { + state->hold[state->hold_len++] = *p++; + length--; + } + if (state->hold_len < LBYTES) + return (ret); + uu_encode(&state->encoded_buff, state->hold, LBYTES); + state->hold_len = 0; + } + + for (; length >= LBYTES; length -= LBYTES, p += LBYTES) + uu_encode(&state->encoded_buff, p, LBYTES); + + /* Save remaining bytes. */ + if (length > 0) { + memcpy(state->hold, p, length); + state->hold_len = length; + } + while (archive_strlen(&state->encoded_buff) >= state->bs) { + ret = __archive_write_filter(f->next_filter, + state->encoded_buff.s, state->bs); + memmove(state->encoded_buff.s, + state->encoded_buff.s + state->bs, + state->encoded_buff.length - state->bs); + state->encoded_buff.length -= state->bs; + } + + return (ret); +} + + +/* + * Finish the compression... + */ +static int +archive_filter_uuencode_close(struct archive_write_filter *f) +{ + struct private_uuencode *state = (struct private_uuencode *)f->data; + int ret, ret2; + + /* Flush remaining bytes. */ + if (state->hold_len != 0) + uu_encode(&state->encoded_buff, state->hold, state->hold_len); + archive_string_sprintf(&state->encoded_buff, "`\nend\n"); + /* Write the last block */ + archive_write_set_bytes_in_last_block(f->archive, 1); + ret = __archive_write_filter(f->next_filter, + state->encoded_buff.s, archive_strlen(&state->encoded_buff)); + ret2 = __archive_write_close_filter(f->next_filter); + if (ret > ret2) + ret = ret2; + return (ret); +} + +static int +archive_filter_uuencode_free(struct archive_write_filter *f) +{ + struct private_uuencode *state = (struct private_uuencode *)f->data; + + archive_string_free(&state->name); + archive_string_free(&state->encoded_buff); + free(state); + return (ARCHIVE_OK); +} + +static int64_t +atol8(const char *p, size_t char_cnt) +{ + int64_t l; + int digit; + + l = 0; + while (char_cnt-- > 0) { + if (*p >= '0' && *p <= '7') + digit = *p - '0'; + else + break; + p++; + l <<= 3; + l |= digit; + } + return (l); +} + diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c index b06775224..fa73311e7 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c @@ -1,6 +1,6 @@ /*- - * Copyright (c) 2009,2010 Michihiro NAKAJIMA * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -172,7 +172,7 @@ archive_write_add_filter_xz(struct archive *_a) f = __archive_write_allocate_filter(_a); r = common_setup(f); if (r == ARCHIVE_OK) { - f->code = ARCHIVE_COMPRESSION_XZ; + f->code = ARCHIVE_FILTER_XZ; f->name = "xz"; } return (r); @@ -192,7 +192,7 @@ archive_write_add_filter_lzma(struct archive *_a) f = __archive_write_allocate_filter(_a); r = common_setup(f); if (r == ARCHIVE_OK) { - f->code = ARCHIVE_COMPRESSION_LZMA; + f->code = ARCHIVE_FILTER_LZMA; f->name = "lzma"; } return (r); @@ -209,7 +209,7 @@ archive_write_add_filter_lzip(struct archive *_a) f = __archive_write_allocate_filter(_a); r = common_setup(f); if (r == ARCHIVE_OK) { - f->code = ARCHIVE_COMPRESSION_LZIP; + f->code = ARCHIVE_FILTER_LZIP; f->name = "lzip"; } return (r); @@ -225,12 +225,12 @@ archive_compressor_xz_init_stream(struct archive_write_filter *f, data->stream = lzma_stream_init_data; data->stream.next_out = data->compressed; data->stream.avail_out = data->compressed_buffer_size; - if (f->code == ARCHIVE_COMPRESSION_XZ) + if (f->code == ARCHIVE_FILTER_XZ) ret = lzma_stream_encoder(&(data->stream), data->lzmafilters, LZMA_CHECK_CRC64); - else if (f->code == ARCHIVE_COMPRESSION_LZMA) + else if (f->code == ARCHIVE_FILTER_LZMA) ret = lzma_alone_encoder(&(data->stream), &data->lzma_opt); - else { /* ARCHIVE_COMPRESSION_LZIP */ + else { /* ARCHIVE_FILTER_LZIP */ int dict_size = data->lzma_opt.dict_size; int ds, log2dic, wedges; @@ -298,7 +298,17 @@ archive_compressor_xz_open(struct archive_write_filter *f) return (ret); if (data->compressed == NULL) { - data->compressed_buffer_size = 65536; + size_t bs = 65536, bpb; + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + data->compressed_buffer_size = bs; data->compressed = (unsigned char *)malloc(data->compressed_buffer_size); if (data->compressed == NULL) { @@ -311,7 +321,7 @@ archive_compressor_xz_open(struct archive_write_filter *f) f->write = archive_compressor_xz_write; /* Initialize compression library. */ - if (f->code == ARCHIVE_COMPRESSION_LZIP) { + if (f->code == ARCHIVE_FILTER_LZIP) { const struct option_value *val = &option_values[data->compression_level]; @@ -365,6 +375,9 @@ archive_compressor_xz_options(struct archive_write_filter *f, return (ARCHIVE_OK); } + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ return (ARCHIVE_WARN); } @@ -380,7 +393,7 @@ archive_compressor_xz_write(struct archive_write_filter *f, /* Update statistics */ data->total_in += length; - if (f->code == ARCHIVE_COMPRESSION_LZIP) + if (f->code == ARCHIVE_FILTER_LZIP) data->crc32 = lzma_crc32(buff, length, data->crc32); /* Compress input data to output buffer */ @@ -409,7 +422,7 @@ archive_compressor_xz_close(struct archive_write_filter *f) ret = __archive_write_filter(f->next_filter, data->compressed, data->compressed_buffer_size - data->stream.avail_out); - if (f->code == ARCHIVE_COMPRESSION_LZIP && ret == ARCHIVE_OK) { + if (f->code == ARCHIVE_FILTER_LZIP && ret == ARCHIVE_OK) { archive_le32enc(data->compressed, data->crc32); archive_le64enc(data->compressed+4, data->total_in); archive_le64enc(data->compressed+12, data->total_out + 20); diff --git a/Utilities/cmlibarchive/libarchive/archive_write_blocksize.3 b/Utilities/cmlibarchive/libarchive/archive_write_blocksize.3 index 96c75382a..afd84ea4d 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_blocksize.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_blocksize.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 23, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_WRITE_BLOCKSIZE 3 .Os .Sh NAME @@ -33,6 +33,8 @@ .Nm archive_write_get_bytes_in_last_block , .Nm archive_write_set_bytes_in_last_block .Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_write_data.3 b/Utilities/cmlibarchive/libarchive/archive_write_data.3 index fc399bc30..cfd5cd552 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_data.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_data.3 @@ -22,14 +22,16 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $ +.\" $FreeBSD$ .\" -.Dd March 23, 2011 -.Dt ARCHIVE_WRITE 3 +.Dd February 2, 2012 +.Dt ARCHIVE_WRITE_DATA 3 .Os .Sh NAME .Nm archive_write_data .Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft ssize_t diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk.3 b/Utilities/cmlibarchive/libarchive/archive_write_disk.3 index ffadb04fe..fa925cc54 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk.3 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/archive_write_disk.3,v 1.4 2008/09/04 05:22:00 kientzle Exp $ +.\" $FreeBSD$ .\" -.Dd August 5, 2008 +.Dd February 2, 2012 .Dt ARCHIVE_WRITE_DISK 3 .Os .Sh NAME @@ -42,6 +42,8 @@ .Nm archive_write_finish .Nm archive_write_free .Nd functions for creating objects on disk +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft struct archive * diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c new file mode 100644 index 000000000..97972033c --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c @@ -0,0 +1,249 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 05:35:40Z kientzle $"); + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_ACL_H +#define _ACL_PRIVATE /* For debugging */ +#include <sys/acl.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_acl_private.h" +#include "archive_write_disk_private.h" + +#if !defined(HAVE_POSIX_ACL) || !defined(ACL_TYPE_NFS4) +/* Default empty function body to satisfy mainline code. */ +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl) +{ + (void)a; /* UNUSED */ + (void)fd; /* UNUSED */ + (void)name; /* UNUSED */ + (void)abstract_acl; /* UNUSED */ + return (ARCHIVE_OK); +} + +#else + +static int set_acl(struct archive *, int fd, const char *, + struct archive_acl *, + acl_type_t, int archive_entry_acl_type, const char *tn); + +/* + * XXX TODO: What about ACL types other than ACCESS and DEFAULT? + */ +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl) +{ + int ret; + + if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) > 0) { + ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); + if (ret != ARCHIVE_OK) + return (ret); + ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); + return (ret); + } else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) { + ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4, + ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); + return (ret); + } else + return ARCHIVE_OK; +} + +static struct { + int archive_perm; + int platform_perm; +} acl_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, + {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +}; + +static struct { + int archive_inherit; + int platform_inherit; +} acl_inherit_map[] = { + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY} +}; + +static int +set_acl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, + acl_type_t acl_type, int ae_requested_type, const char *tname) +{ + acl_t acl; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + acl_flagset_t acl_flagset; + int ret; + int ae_type, ae_permset, ae_tag, ae_id; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + acl = acl_init(entries); + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + acl_create_entry(&acl, &acl_entry); + + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + acl_set_tag_type(acl_entry, ACL_USER); + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + acl_set_qualifier(acl_entry, &ae_uid); + break; + case ARCHIVE_ENTRY_ACL_GROUP: + acl_set_tag_type(acl_entry, ACL_GROUP); + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + acl_set_qualifier(acl_entry, &ae_gid); + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + acl_set_tag_type(acl_entry, ACL_USER_OBJ); + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); + break; + case ARCHIVE_ENTRY_ACL_MASK: + acl_set_tag_type(acl_entry, ACL_MASK); + break; + case ARCHIVE_ENTRY_ACL_OTHER: + acl_set_tag_type(acl_entry, ACL_OTHER); + break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + acl_set_tag_type(acl_entry, ACL_EVERYONE); + break; + default: + /* XXX */ + break; + } + + switch (ae_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + // These don't translate directly into the system ACL. + break; + default: + // XXX error handling here. + break; + } + + acl_get_permset(acl_entry, &acl_permset); + acl_clear_perms(acl_permset); + + for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { + if (ae_permset & acl_perm_map[i].archive_perm) + acl_add_perm(acl_permset, + acl_perm_map[i].platform_perm); + } + + acl_get_flagset_np(acl_entry, &acl_flagset); + acl_clear_flags_np(acl_flagset); + for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { + if (ae_permset & acl_inherit_map[i].archive_inherit) + acl_add_flag_np(acl_flagset, + acl_inherit_map[i].platform_inherit); + } + } + + /* Try restoring the ACL through 'fd' if we can. */ +#if HAVE_ACL_SET_FD + if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0) + ret = ARCHIVE_OK; + else +#else +#if HAVE_ACL_SET_FD_NP + if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0) + ret = ARCHIVE_OK; + else +#endif +#endif +#if HAVE_ACL_SET_LINK_NP + if (acl_set_link_np(name, acl_type, acl) != 0) { + archive_set_error(a, errno, "Failed to set %s acl", tname); + ret = ARCHIVE_WARN; + } +#else + /* TODO: Skip this if 'name' is a symlink. */ + if (acl_set_file(name, acl_type, acl) != 0) { + archive_set_error(a, errno, "Failed to set %s acl", tname); + ret = ARCHIVE_WARN; + } +#endif + acl_free(acl); + return (ret); +} +#endif diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c index 99afab2f6..b69c8739d 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,15 +39,14 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_SYS_EXTATTR_H #include <sys/extattr.h> #endif -#ifdef HAVE_SYS_XATTR_H +#if defined(HAVE_SYS_XATTR_H) #include <sys/xattr.h> +#elif defined(HAVE_ATTR_XATTR_H) +#include <attr/xattr.h> #endif #ifdef HAVE_SYS_EA_H #include <sys/ea.h> #endif -#ifdef HAVE_ATTR_XATTR_H -#include <attr/xattr.h> -#endif #ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> #endif @@ -118,6 +118,10 @@ __FBSDID("$FreeBSD$"); #endif #endif +#ifdef HAVE_ZLIB_H +#include <cm_zlib.h> +#endif + /* TODO: Support Mac OS 'quarantine' feature. This is really just a * standard tag to mark files that have been downloaded as "tainted". * On Mac OS, we should mark the extracted files as tainted if the @@ -127,12 +131,17 @@ __FBSDID("$FreeBSD$"); #include "archive.h" #include "archive_acl_private.h" #include "archive_string.h" +#include "archive_endian.h" #include "archive_entry.h" #include "archive_private.h" +#include "archive_write_disk_private.h" #ifndef O_BINARY #define O_BINARY 0 #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif struct fixup_entry { struct fixup_entry *next; @@ -172,6 +181,7 @@ struct fixup_entry { #define TODO_SUID_CHECK 0x08000000 #define TODO_SGID 0x04000000 #define TODO_SGID_CHECK 0x02000000 +#define TODO_APPLEDOUBLE 0x01000000 #define TODO_MODE (TODO_MODE_BASE|TODO_SUID|TODO_SGID) #define TODO_TIMES ARCHIVE_EXTRACT_TIME #define TODO_OWNER ARCHIVE_EXTRACT_OWNER @@ -179,6 +189,7 @@ struct fixup_entry { #define TODO_ACLS ARCHIVE_EXTRACT_ACL #define TODO_XATTR ARCHIVE_EXTRACT_XATTR #define TODO_MAC_METADATA ARCHIVE_EXTRACT_MAC_METADATA +#define TODO_HFS_COMPRESSION ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED struct archive_write_disk { struct archive archive; @@ -188,8 +199,8 @@ struct archive_write_disk { struct fixup_entry *current_fixup; int64_t user_uid; int skip_file_set; - dev_t skip_file_dev; - ino_t skip_file_ino; + int64_t skip_file_dev; + int64_t skip_file_ino; time_t start_time; int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid); @@ -239,6 +250,36 @@ struct archive_write_disk { /* UID/GID to use in restoring this entry. */ int64_t uid; int64_t gid; + /* + * HFS+ Compression. + */ + /* Xattr "com.apple.decmpfs". */ + uint32_t decmpfs_attr_size; + unsigned char *decmpfs_header_p; + /* ResourceFork set options used for fsetxattr. */ + int rsrc_xattr_options; + /* Xattr "com.apple.ResourceFork". */ + unsigned char *resource_fork; + size_t resource_fork_allocated_size; + unsigned int decmpfs_block_count; + uint32_t *decmpfs_block_info; + /* Buffer for compressed data. */ + unsigned char *compressed_buffer; + size_t compressed_buffer_size; + size_t compressed_buffer_remaining; + /* The offset of the ResourceFork where compressed data will + * be placed. */ + uint32_t compressed_rsrc_position; + uint32_t compressed_rsrc_position_v; + /* Buffer for uncompressed data. */ + char *uncompressed_buffer; + size_t block_remaining_bytes; + size_t file_remaining_bytes; +#ifdef HAVE_ZLIB_H + z_stream stream; + int stream_valid; + int decmpfs_compression_level; +#endif }; /* @@ -256,6 +297,35 @@ struct archive_write_disk { #define MINIMUM_DIR_MODE 0700 #define MAXIMUM_DIR_MODE 0775 +/* + * Maxinum uncompressed size of a decmpfs block. + */ +#define MAX_DECMPFS_BLOCK_SIZE (64 * 1024) +/* + * HFS+ compression type. + */ +#define CMP_XATTR 3/* Compressed data in xattr. */ +#define CMP_RESOURCE_FORK 4/* Compressed data in resource fork. */ +/* + * HFS+ compression resource fork. + */ +#define RSRC_H_SIZE 260 /* Base size of Resource fork header. */ +#define RSRC_F_SIZE 50 /* Size of Resource fork footer. */ +/* Size to write compressed data to resource fork. */ +#define COMPRESSED_W_SIZE (64 * 1024) +/* decmpfs difinitions. */ +#define MAX_DECMPFS_XATTR_SIZE 3802 +#ifndef DECMPFS_XATTR_NAME +#define DECMPFS_XATTR_NAME "com.apple.decmpfs" +#endif +#define DECMPFS_MAGIC 0x636d7066 +#define DECMPFS_COMPRESSION_MAGIC 0 +#define DECMPFS_COMPRESSION_TYPE 4 +#define DECMPFS_UNCOMPRESSED_SIZE 8 +#define DECMPFS_HEADER_SIZE 16 + +#define HFS_BLOCKS(s) ((s) >> 12) + static int check_symlinks(struct archive_write_disk *); static int create_filesystem_object(struct archive_write_disk *); static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname); @@ -265,13 +335,11 @@ static void edit_deep_directories(struct archive_write_disk *ad); static int cleanup_pathname(struct archive_write_disk *); static int create_dir(struct archive_write_disk *, char *); static int create_parent_dir(struct archive_write_disk *, char *); +static ssize_t hfs_write_data_block(struct archive_write_disk *, + const char *, size_t); +static int fixup_appledouble(struct archive_write_disk *, const char *); static int older(struct stat *, struct archive_entry *); static int restore_entry(struct archive_write_disk *); -#ifdef HAVE_POSIX_ACL -static int set_acl(struct archive_write_disk *, int fd, const char *, struct archive_acl *, - acl_type_t, int archive_entry_acl_type, const char *tn); -#endif -static int set_acls(struct archive_write_disk *, int fd, const char *, struct archive_acl *); static int set_mac_metadata(struct archive_write_disk *, const char *, const void *, size_t); static int set_xattrs(struct archive_write_disk *); @@ -485,6 +553,39 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) else a->todo |= TODO_MAC_METADATA; } +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + if ((a->flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) == 0) { + unsigned long set, clear; + archive_entry_fflags(a->entry, &set, &clear); + if ((set & ~clear) & UF_COMPRESSED) { + a->todo |= TODO_HFS_COMPRESSION; + a->decmpfs_block_count = (unsigned)-1; + } + } + if ((a->flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) != 0 && + (a->mode & AE_IFMT) == AE_IFREG && a->filesize > 0) { + a->todo |= TODO_HFS_COMPRESSION; + a->decmpfs_block_count = (unsigned)-1; + } + { + const char *p; + + /* Check if the current file name is a type of the + * resource fork file. */ + p = strrchr(a->name, '/'); + if (p == NULL) + p = a->name; + else + p++; + if (p[0] == '.' && p[1] == '_') { + /* Do not compress "._XXX" files. */ + a->todo &= ~TODO_HFS_COMPRESSION; + if (a->filesize > 0) + a->todo |= TODO_APPLEDOUBLE; + } + } +#endif + if (a->flags & ARCHIVE_EXTRACT_XATTR) a->todo |= TODO_XATTR; if (a->flags & ARCHIVE_EXTRACT_FFLAGS) @@ -501,6 +602,25 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) ret = restore_entry(a); +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + /* + * Check if the filesystem the file is restoring on supports + * HFS+ Compression. If not, cancel HFS+ Compression. + */ + if (a->todo | TODO_HFS_COMPRESSION) { + /* + * NOTE: UF_COMPRESSED is ignored even if the filesystem + * supports HFS+ Compression because the file should + * have at least an extended attriute "com.apple.decmpfs" + * before the flag is set to indicate that the file have + * been compressed. If hte filesystem does not support + * HFS+ Compression the system call will fail. + */ + if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0) + a->todo &= ~TODO_HFS_COMPRESSION; + } +#endif + /* * TODO: There are rumours that some extended attributes must * be restored before file data is written. If this is true, @@ -532,6 +652,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) */ if (a->deferred & TODO_MODE) { fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); fe->fixup |= TODO_MODE_BASE; fe->mode = a->mode; } @@ -540,6 +662,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) && (archive_entry_mtime_is_set(entry) || archive_entry_atime_is_set(entry))) { fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); fe->mode = a->mode; fe->fixup |= TODO_TIMES; if (archive_entry_atime_is_set(entry)) { @@ -570,6 +694,9 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) if (a->deferred & TODO_ACLS) { fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->fixup |= TODO_ACLS; archive_acl_copy(&fe->acl, archive_entry_acl(entry)); } @@ -579,6 +706,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) metadata = archive_entry_mac_metadata(a->entry, &metadata_size); if (metadata != NULL && metadata_size > 0) { fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); fe->mac_metadata = malloc(metadata_size); if (fe->mac_metadata != NULL) { memcpy(fe->mac_metadata, metadata, metadata_size); @@ -590,6 +719,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) if (a->deferred & TODO_FFLAGS) { fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); fe->fixup |= TODO_FFLAGS; /* TODO: Complete this.. defer fflags from below. */ } @@ -707,6 +838,616 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size) return (start_size - size); } +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) + +/* + * Set UF_COMPRESSED file flag. + * This have to be called after hfs_write_decmpfs() because if the + * file does not have "com.apple.decmpfs" xattr the flag is ignored. + */ +static int +hfs_set_compressed_fflag(struct archive_write_disk *a) +{ + int r; + + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + + a->st.st_flags |= UF_COMPRESSED; + if (fchflags(a->fd, a->st.st_flags) != 0) { + archive_set_error(&a->archive, errno, + "Failed to set UF_COMPRESSED file flag"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +/* + * HFS+ Compression decmpfs + * + * +------------------------------+ +0 + * | Magic(LE 4 bytes) | + * +------------------------------+ + * | Type(LE 4 bytes) | + * +------------------------------+ + * | Uncompressed size(LE 8 bytes)| + * +------------------------------+ +16 + * | | + * | Compressed data | + * | (Placed only if Type == 3) | + * | | + * +------------------------------+ +3802 = MAX_DECMPFS_XATTR_SIZE + * + * Type is 3: decmpfs has compressed data. + * Type is 4: Resource Fork has compressed data. + */ +/* + * Write "com.apple.decmpfs" + */ +static int +hfs_write_decmpfs(struct archive_write_disk *a) +{ + int r; + uint32_t compression_type; + + r = fsetxattr(a->fd, DECMPFS_XATTR_NAME, a->decmpfs_header_p, + a->decmpfs_attr_size, 0, 0); + if (r < 0) { + archive_set_error(&a->archive, errno, + "Cannot restore xattr:%s", DECMPFS_XATTR_NAME); + compression_type = archive_le32dec( + &a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE]); + if (compression_type == CMP_RESOURCE_FORK) + fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, + XATTR_SHOWCOMPRESSION); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +/* + * HFS+ Compression Resource Fork + * + * +-----------------------------+ + * | Header(260 bytes) | + * +-----------------------------+ + * | Block count(LE 4 bytes) | + * +-----------------------------+ --+ + * +-- | Offset (LE 4 bytes) | | + * | | [distance from Block count] | | Block 0 + * | +-----------------------------+ | + * | | Compressed size(LE 4 bytes) | | + * | +-----------------------------+ --+ + * | | | + * | | .................. | + * | | | + * | +-----------------------------+ --+ + * | | Offset (LE 4 bytes) | | + * | +-----------------------------+ | Block (Block count -1) + * | | Compressed size(LE 4 bytes) | | + * +-> +-----------------------------+ --+ + * | Compressed data(n bytes) | Block 0 + * +-----------------------------+ + * | | + * | .................. | + * | | + * +-----------------------------+ + * | Compressed data(n bytes) | Block (Block count -1) + * +-----------------------------+ + * | Footer(50 bytes) | + * +-----------------------------+ + * + */ +/* + * Write the header of "com.apple.ResourceFork" + */ +static int +hfs_write_resource_fork(struct archive_write_disk *a, unsigned char *buff, + size_t bytes, uint32_t position) +{ + int ret; + + ret = fsetxattr(a->fd, XATTR_RESOURCEFORK_NAME, buff, bytes, + position, a->rsrc_xattr_options); + if (ret < 0) { + archive_set_error(&a->archive, errno, + "Cannot restore xattr: %s at %u pos %u bytes", + XATTR_RESOURCEFORK_NAME, + (unsigned)position, + (unsigned)bytes); + return (ARCHIVE_WARN); + } + a->rsrc_xattr_options &= ~XATTR_CREATE; + return (ARCHIVE_OK); +} + +static int +hfs_write_compressed_data(struct archive_write_disk *a, size_t bytes_compressed) +{ + int ret; + + ret = hfs_write_resource_fork(a, a->compressed_buffer, + bytes_compressed, a->compressed_rsrc_position); + if (ret == ARCHIVE_OK) + a->compressed_rsrc_position += bytes_compressed; + return (ret); +} + +static int +hfs_write_resource_fork_header(struct archive_write_disk *a) +{ + unsigned char *buff; + uint32_t rsrc_bytes; + uint32_t rsrc_header_bytes; + + /* + * Write resource fork header + block info. + */ + buff = a->resource_fork; + rsrc_bytes = a->compressed_rsrc_position - RSRC_F_SIZE; + rsrc_header_bytes = + RSRC_H_SIZE + /* Header base size. */ + 4 + /* Block count. */ + (a->decmpfs_block_count * 8);/* Block info */ + archive_be32enc(buff, 0x100); + archive_be32enc(buff + 4, rsrc_bytes); + archive_be32enc(buff + 8, rsrc_bytes - 256); + archive_be32enc(buff + 12, 0x32); + memset(buff + 16, 0, 240); + archive_be32enc(buff + 256, rsrc_bytes - 260); + return hfs_write_resource_fork(a, buff, rsrc_header_bytes, 0); +} + +static size_t +hfs_set_resource_fork_footer(unsigned char *buff, size_t buff_size) +{ + static const char rsrc_footer[RSRC_F_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c', 'm', + 'p', 'f', 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + if (buff_size < sizeof(rsrc_footer)) + return (0); + memcpy(buff, rsrc_footer, sizeof(rsrc_footer)); + return (sizeof(rsrc_footer)); +} + +static int +hfs_reset_compressor(struct archive_write_disk *a) +{ + int ret; + + if (a->stream_valid) + ret = deflateReset(&a->stream); + else + ret = deflateInit(&a->stream, a->decmpfs_compression_level); + + if (ret != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to initialize compressor"); + return (ARCHIVE_FATAL); + } else + a->stream_valid = 1; + + return (ARCHIVE_OK); +} + +static int +hfs_decompress(struct archive_write_disk *a) +{ + uint32_t *block_info; + unsigned int block_count; + uint32_t data_pos, data_size; + ssize_t r; + ssize_t bytes_written, bytes_to_write; + unsigned char *b; + + block_info = (uint32_t *)(a->resource_fork + RSRC_H_SIZE); + block_count = archive_le32dec(block_info++); + while (block_count--) { + data_pos = RSRC_H_SIZE + archive_le32dec(block_info++); + data_size = archive_le32dec(block_info++); + r = fgetxattr(a->fd, XATTR_RESOURCEFORK_NAME, + a->compressed_buffer, data_size, data_pos, 0); + if (r != data_size) { + archive_set_error(&a->archive, + (r < 0)?errno:ARCHIVE_ERRNO_MISC, + "Failed to read resource fork"); + return (ARCHIVE_WARN); + } + if (a->compressed_buffer[0] == 0xff) { + bytes_to_write = data_size -1; + b = a->compressed_buffer + 1; + } else { + uLong dest_len = MAX_DECMPFS_BLOCK_SIZE; + int zr; + + zr = uncompress((Bytef *)a->uncompressed_buffer, + &dest_len, a->compressed_buffer, data_size); + if (zr != Z_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to decompress resource fork"); + return (ARCHIVE_WARN); + } + bytes_to_write = dest_len; + b = (unsigned char *)a->uncompressed_buffer; + } + do { + bytes_written = write(a->fd, b, bytes_to_write); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, + "Write failed"); + return (ARCHIVE_WARN); + } + bytes_to_write -= bytes_written; + b += bytes_written; + } while (bytes_to_write > 0); + } + r = fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, 0); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to remove resource fork"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +hfs_drive_compressor(struct archive_write_disk *a, const char *buff, + size_t size) +{ + unsigned char *buffer_compressed; + size_t bytes_compressed; + size_t bytes_used; + int ret; + + ret = hfs_reset_compressor(a); + if (ret != ARCHIVE_OK) + return (ret); + + if (a->compressed_buffer == NULL) { + size_t block_size; + + block_size = COMPRESSED_W_SIZE + RSRC_F_SIZE + + + compressBound(MAX_DECMPFS_BLOCK_SIZE); + a->compressed_buffer = malloc(block_size); + if (a->compressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Resource Fork"); + return (ARCHIVE_FATAL); + } + a->compressed_buffer_size = block_size; + a->compressed_buffer_remaining = block_size; + } + + buffer_compressed = a->compressed_buffer + + a->compressed_buffer_size - a->compressed_buffer_remaining; + a->stream.next_in = (Bytef *)(uintptr_t)(const void *)buff; + a->stream.avail_in = size; + a->stream.next_out = buffer_compressed; + a->stream.avail_out = a->compressed_buffer_remaining; + do { + ret = deflate(&a->stream, Z_FINISH); + switch (ret) { + case Z_OK: + case Z_STREAM_END: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to compress data"); + return (ARCHIVE_FAILED); + } + } while (ret == Z_OK); + bytes_compressed = a->compressed_buffer_remaining - a->stream.avail_out; + + /* + * If the compressed size is larger than the original size, + * throw away compressed data, use uncompressed data instead. + */ + if (bytes_compressed > size) { + buffer_compressed[0] = 0xFF;/* uncompressed marker. */ + memcpy(buffer_compressed + 1, buff, size); + bytes_compressed = size + 1; + } + a->compressed_buffer_remaining -= bytes_compressed; + + /* + * If the compressed size is smaller than MAX_DECMPFS_XATTR_SIZE + * and the block count in the file is only one, store compressed + * data to decmpfs xattr instead of the resource fork. + */ + if (a->decmpfs_block_count == 1 && + (a->decmpfs_attr_size + bytes_compressed) + <= MAX_DECMPFS_XATTR_SIZE) { + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE], + CMP_XATTR); + memcpy(a->decmpfs_header_p + DECMPFS_HEADER_SIZE, + buffer_compressed, bytes_compressed); + a->decmpfs_attr_size += bytes_compressed; + a->compressed_buffer_remaining = a->compressed_buffer_size; + /* + * Finish HFS+ Compression. + * - Write the decmpfs xattr. + * - Set the UF_COMPRESSED file flag. + */ + ret = hfs_write_decmpfs(a); + if (ret == ARCHIVE_OK) + ret = hfs_set_compressed_fflag(a); + return (ret); + } + + /* Update block info. */ + archive_le32enc(a->decmpfs_block_info++, + a->compressed_rsrc_position_v - RSRC_H_SIZE); + archive_le32enc(a->decmpfs_block_info++, bytes_compressed); + a->compressed_rsrc_position_v += bytes_compressed; + + /* + * Write the compressed data to the resource fork. + */ + bytes_used = a->compressed_buffer_size - a->compressed_buffer_remaining; + while (bytes_used >= COMPRESSED_W_SIZE) { + ret = hfs_write_compressed_data(a, COMPRESSED_W_SIZE); + if (ret != ARCHIVE_OK) + return (ret); + bytes_used -= COMPRESSED_W_SIZE; + if (bytes_used > COMPRESSED_W_SIZE) + memmove(a->compressed_buffer, + a->compressed_buffer + COMPRESSED_W_SIZE, + bytes_used); + else + memcpy(a->compressed_buffer, + a->compressed_buffer + COMPRESSED_W_SIZE, + bytes_used); + } + a->compressed_buffer_remaining = a->compressed_buffer_size - bytes_used; + + /* + * If the current block is the last block, write the remaining + * compressed data and the resource fork footer. + */ + if (a->file_remaining_bytes == 0) { + size_t rsrc_size; + int64_t bk; + + /* Append the resource footer. */ + rsrc_size = hfs_set_resource_fork_footer( + a->compressed_buffer + bytes_used, + a->compressed_buffer_remaining); + ret = hfs_write_compressed_data(a, bytes_used + rsrc_size); + a->compressed_buffer_remaining = a->compressed_buffer_size; + + /* If the compressed size is not enouph smaller than + * the uncompressed size. cancel HFS+ compression. + * TODO: study a behavior of ditto utility and improve + * the condition to fall back into no HFS+ compression. */ + bk = HFS_BLOCKS(a->compressed_rsrc_position); + bk += bk >> 7; + if (bk > HFS_BLOCKS(a->filesize)) + return hfs_decompress(a); + /* + * Write the resourcefork header. + */ + if (ret == ARCHIVE_OK) + ret = hfs_write_resource_fork_header(a); + /* + * Finish HFS+ Compression. + * - Write the decmpfs xattr. + * - Set the UF_COMPRESSED file flag. + */ + if (ret == ARCHIVE_OK) + ret = hfs_write_decmpfs(a); + if (ret == ARCHIVE_OK) + ret = hfs_set_compressed_fflag(a); + } + return (ret); +} + +static ssize_t +hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + const char *buffer_to_write; + size_t bytes_to_write; + int ret; + + if (a->decmpfs_block_count == (unsigned)-1) { + void *new_block; + size_t new_size; + unsigned int block_count; + + if (a->decmpfs_header_p == NULL) { + new_block = malloc(MAX_DECMPFS_XATTR_SIZE + + sizeof(uint32_t)); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for decmpfs"); + return (ARCHIVE_FATAL); + } + a->decmpfs_header_p = new_block; + } + a->decmpfs_attr_size = DECMPFS_HEADER_SIZE; + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_MAGIC], + DECMPFS_MAGIC); + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE], + CMP_RESOURCE_FORK); + archive_le64enc(&a->decmpfs_header_p[DECMPFS_UNCOMPRESSED_SIZE], + a->filesize); + + /* Calculate a block count of the file. */ + block_count = + (a->filesize + MAX_DECMPFS_BLOCK_SIZE -1) / + MAX_DECMPFS_BLOCK_SIZE; + /* + * Allocate buffer for resource fork. + * Set up related pointers; + */ + new_size = + RSRC_H_SIZE + /* header */ + 4 + /* Block count */ + (block_count * sizeof(uint32_t) * 2) + + RSRC_F_SIZE; /* footer */ + if (new_size > a->resource_fork_allocated_size) { + new_block = realloc(a->resource_fork, new_size); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for ResourceFork"); + return (ARCHIVE_FATAL); + } + a->resource_fork_allocated_size = new_size; + a->resource_fork = new_block; + } + + /* Allocate uncompressed buffer */ + if (a->uncompressed_buffer == NULL) { + new_block = malloc(MAX_DECMPFS_BLOCK_SIZE); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for decmpfs"); + return (ARCHIVE_FATAL); + } + a->uncompressed_buffer = new_block; + } + a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE; + a->file_remaining_bytes = a->filesize; + a->compressed_buffer_remaining = a->compressed_buffer_size; + + /* + * Set up a resource fork. + */ + a->rsrc_xattr_options = XATTR_CREATE; + /* Get the position where we are going to set a bunch + * of block info. */ + a->decmpfs_block_info = + (uint32_t *)(a->resource_fork + RSRC_H_SIZE); + /* Set the block count to the resource fork. */ + archive_le32enc(a->decmpfs_block_info++, block_count); + /* Get the position where we are goint to set compressed + * data. */ + a->compressed_rsrc_position = + RSRC_H_SIZE + 4 + (block_count * 8); + a->compressed_rsrc_position_v = a->compressed_rsrc_position; + a->decmpfs_block_count = block_count; + } + + /* Ignore redundant bytes. */ + if (a->file_remaining_bytes == 0) + return ((ssize_t)size); + + /* Do not overrun a block size. */ + if (size > a->block_remaining_bytes) + bytes_to_write = a->block_remaining_bytes; + else + bytes_to_write = size; + /* Do not overrun the file size. */ + if (bytes_to_write > a->file_remaining_bytes) + bytes_to_write = a->file_remaining_bytes; + + /* For efficiency, if a copy length is full of the uncompressed + * buffer size, do not copy writing data to it. */ + if (bytes_to_write == MAX_DECMPFS_BLOCK_SIZE) + buffer_to_write = buff; + else { + memcpy(a->uncompressed_buffer + + MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes, + buff, bytes_to_write); + buffer_to_write = a->uncompressed_buffer; + } + a->block_remaining_bytes -= bytes_to_write; + a->file_remaining_bytes -= bytes_to_write; + + if (a->block_remaining_bytes == 0 || a->file_remaining_bytes == 0) { + ret = hfs_drive_compressor(a, buffer_to_write, + MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes); + if (ret < 0) + return (ret); + a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE; + } + /* Ignore redundant bytes. */ + if (a->file_remaining_bytes == 0) + return ((ssize_t)size); + return (bytes_to_write); +} + +static ssize_t +hfs_write_data_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + uint64_t start_size = size; + ssize_t bytes_written = 0; + ssize_t bytes_to_write; + + if (size == 0) + return (ARCHIVE_OK); + + if (a->filesize == 0 || a->fd < 0) { + archive_set_error(&a->archive, 0, + "Attempt to write to an empty file"); + return (ARCHIVE_WARN); + } + + /* If this write would run beyond the file size, truncate it. */ + if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize) + start_size = size = (size_t)(a->filesize - a->offset); + + /* Write the data. */ + while (size > 0) { + bytes_to_write = size; + /* Seek if necessary to the specified offset. */ + if (a->offset < a->fd_offset) { + /* Can't support backword move. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Seek failed"); + return (ARCHIVE_FATAL); + } else if (a->offset > a->fd_offset) { + int64_t skip = a->offset - a->fd_offset; + char nullblock[1024]; + + memset(nullblock, 0, sizeof(nullblock)); + while (skip > 0) { + if (skip > (int64_t)sizeof(nullblock)) + bytes_written = hfs_write_decmpfs_block( + a, nullblock, sizeof(nullblock)); + else + bytes_written = hfs_write_decmpfs_block( + a, nullblock, skip); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, + "Write failed"); + return (ARCHIVE_WARN); + } + skip -= bytes_written; + } + + a->fd_offset = a->offset; + } + bytes_written = + hfs_write_decmpfs_block(a, buff, bytes_to_write); + if (bytes_written < 0) + return (bytes_written); + buff += bytes_written; + size -= bytes_written; + a->total_bytes_written += bytes_written; + a->offset += bytes_written; + a->fd_offset = a->offset; + } + return (start_size - size); +} +#else +static ssize_t +hfs_write_data_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + return (write_data_block(a, buff, size)); +} +#endif + static ssize_t _archive_write_disk_data_block(struct archive *_a, const void *buff, size_t size, int64_t offset) @@ -718,7 +1459,10 @@ _archive_write_disk_data_block(struct archive *_a, ARCHIVE_STATE_DATA, "archive_write_data_block"); a->offset = offset; - r = write_data_block(a, buff, size); + if (a->todo & TODO_HFS_COMPRESSION) + r = hfs_write_data_block(a, buff, size); + else + r = write_data_block(a, buff, size); if (r < ARCHIVE_OK) return (r); if ((size_t)r < size) { @@ -737,6 +1481,8 @@ _archive_write_disk_data(struct archive *_a, const void *buff, size_t size) archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, ARCHIVE_STATE_DATA, "archive_write_data"); + if (a->todo & TODO_HFS_COMPRESSION) + return (hfs_write_data_block(a, buff, size)); return (write_data_block(a, buff, size)); } @@ -761,6 +1507,24 @@ _archive_write_disk_finish_entry(struct archive *_a) } else if (a->fd_offset == a->filesize) { /* Last write ended at exactly the filesize; we're done. */ /* Hopefully, this is the common case. */ +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + } else if (a->todo & TODO_HFS_COMPRESSION) { + char null_d[1024]; + ssize_t r; + + if (a->file_remaining_bytes) + memset(null_d, 0, sizeof(null_d)); + while (a->file_remaining_bytes) { + if (a->file_remaining_bytes > sizeof(null_d)) + r = hfs_write_data_block( + a, null_d, sizeof(null_d)); + else + r = hfs_write_data_block( + a, null_d, a->file_remaining_bytes); + if (r < 0) + return ((int)r); + } +#endif } else { #if HAVE_FTRUNCATE if (ftruncate(a->fd, a->filesize) == -1 && @@ -799,6 +1563,22 @@ _archive_write_disk_finish_entry(struct archive *_a) /* Restore metadata. */ /* + * This is specific to Mac OS X. + * If the current file is an AppleDouble file, it should be + * linked with the data fork file and remove it. + */ + if (a->todo & TODO_APPLEDOUBLE) { + int r2 = fixup_appledouble(a, a->name); + if (r2 == ARCHIVE_EOF) { + /* The current file has been successfully linked + * with the data fork file and removed. So there + * is nothing to do on the current file. */ + goto finish_metadata; + } + if (r2 < ret) ret = r2; + } + + /* * Look up the "real" UID only if we're going to need it. * TODO: the TODO_SGID condition can be dropped here, can't it? */ @@ -820,8 +1600,10 @@ _archive_write_disk_finish_entry(struct archive *_a) * bits. If we set the owner, we know what it is and can skip * a stat() call to examine the ownership of the file on disk. */ - if (a->todo & TODO_OWNER) - ret = set_ownership(a); + if (a->todo & TODO_OWNER) { + int r2 = set_ownership(a); + if (r2 < ret) ret = r2; + } /* * set_mode must precede ACLs on systems such as Solaris and @@ -868,7 +1650,8 @@ _archive_write_disk_finish_entry(struct archive *_a) size_t metadata_size; metadata = archive_entry_mac_metadata(a->entry, &metadata_size); if (metadata != NULL && metadata_size > 0) { - int r2 = set_mac_metadata(a, archive_entry_pathname(a->entry), metadata, metadata_size); + int r2 = set_mac_metadata(a, archive_entry_pathname( + a->entry), metadata, metadata_size); if (r2 < ret) ret = r2; } } @@ -878,12 +1661,13 @@ _archive_write_disk_finish_entry(struct archive *_a) * ACLs that prevent attribute changes (including time). */ if (a->todo & TODO_ACLS) { - int r2 = set_acls(a, a->fd, + int r2 = archive_write_disk_set_acls(&a->archive, a->fd, archive_entry_pathname(a->entry), archive_entry_acl(a->entry)); if (r2 < ret) ret = r2; } +finish_metadata: /* If there's an fd, we can close it now. */ if (a->fd >= 0) { close(a->fd); @@ -950,12 +1734,12 @@ archive_write_disk_gid(struct archive *_a, const char *name, int64_t id) int64_t archive_write_disk_uid(struct archive *_a, const char *name, int64_t id) { - struct archive_write_disk *a = (struct archive_write_disk *)_a; - archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, - ARCHIVE_STATE_ANY, "archive_write_disk_uid"); - if (a->lookup_uid) - return (a->lookup_uid)(a->lookup_uid_data, name, id); - return (id); + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_uid"); + if (a->lookup_uid) + return (a->lookup_uid)(a->lookup_uid_data, name, id); + return (id); } /* @@ -984,6 +1768,9 @@ archive_write_disk_new(void) free(a); return (NULL); } +#ifdef HAVE_ZLIB_H + a->decmpfs_compression_level = 5; +#endif return (&a->archive); } @@ -1008,7 +1795,8 @@ edit_deep_directories(struct archive_write_disk *a) return; /* Try to record our starting dir. */ - a->restore_pwd = open(".", O_RDONLY | O_BINARY); + a->restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(a->restore_pwd); if (a->restore_pwd < 0) return; @@ -1143,9 +1931,10 @@ restore_entry(struct archive_write_disk *a) /* If it's our archive, we're done. */ if (a->skip_file_set && - a->st.st_dev == a->skip_file_dev && - a->st.st_ino == a->skip_file_ino) { - archive_set_error(&a->archive, 0, "Refusing to overwrite archive"); + a->st.st_dev == (dev_t)a->skip_file_dev && + a->st.st_ino == (ino_t)a->skip_file_ino) { + archive_set_error(&a->archive, 0, + "Refusing to overwrite archive"); return (ARCHIVE_FAILED); } @@ -1163,7 +1952,7 @@ restore_entry(struct archive_write_disk *a) /* A dir is in the way of a non-dir, rmdir it. */ if (rmdir(a->name) != 0) { archive_set_error(&a->archive, errno, - "Can't remove already-existing dir"); + "Can't replace existing directory with non-directory"); return (ARCHIVE_FAILED); } /* Try again. */ @@ -1223,7 +2012,7 @@ create_filesystem_object(struct archive_write_disk *a) * * If the hardlink was successfully created and * the archive doesn't have carry data for it, - * consider it to be non-authoritive for meta data. + * consider it to be non-authoritative for meta data. * This is consistent with GNU tar and BSD pax. * If the hardlink does carry data, let the last * archive entry decide ownership. @@ -1232,7 +2021,9 @@ create_filesystem_object(struct archive_write_disk *a) a->todo = 0; a->deferred = 0; } else if (r == 0 && a->filesize > 0) { - a->fd = open(a->name, O_WRONLY | O_TRUNC | O_BINARY); + a->fd = open(a->name, + O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(a->fd); if (a->fd < 0) r = errno; } @@ -1261,7 +2052,7 @@ create_filesystem_object(struct archive_write_disk *a) * that SUID, SGID, etc, require additional work to ensure * security, so we never restore them at this point. */ - mode = final_mode & 0777 & a->user_umask; + mode = final_mode & 0777 & ~a->user_umask; switch (a->mode & AE_IFMT) { default: @@ -1269,7 +2060,8 @@ create_filesystem_object(struct archive_write_disk *a) /* FALLTHROUGH */ case AE_IFREG: a->fd = open(a->name, - O_WRONLY | O_CREAT | O_EXCL | O_BINARY, mode); + O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode); + __archive_ensure_cloexec_flag(a->fd); r = (a->fd < 0); break; case AE_IFCHR: @@ -1380,7 +2172,8 @@ _archive_write_disk_close(struct archive *_a) if (p->fixup & TODO_MODE_BASE) chmod(p->name, p->mode); if (p->fixup & TODO_ACLS) - set_acls(a, -1, p->name, &p->acl); + archive_write_disk_set_acls(&a->archive, + -1, p->name, &p->acl); if (p->fixup & TODO_FFLAGS) set_fflags_platform(a, -1, p->name, p->mode, p->fflags_set, 0); @@ -1418,6 +2211,23 @@ _archive_write_disk_free(struct archive *_a) archive_string_free(&a->path_safe); a->archive.magic = 0; __archive_clean(&a->archive); + free(a->decmpfs_header_p); + free(a->resource_fork); + free(a->compressed_buffer); + free(a->uncompressed_buffer); +#ifdef HAVE_ZLIB_H + if (a->stream_valid) { + switch (deflateEnd(&a->stream)) { + case Z_OK: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + ret = ARCHIVE_FATAL; + break; + } + } +#endif free(a); return (ret); } @@ -1499,8 +2309,11 @@ new_fixup(struct archive_write_disk *a, const char *pathname) struct fixup_entry *fe; fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry)); - if (fe == NULL) + if (fe == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a fixup"); return (NULL); + } fe->next = a->fixup_list; a->fixup_list = fe; fe->fixup = 0; @@ -1672,7 +2485,7 @@ cleanup_pathname_win(struct archive_write_disk *a) p = a->name; while (*p != '\0' && alen) { l = mbtowc(&wc, p, alen); - if (l == -1) { + if (l == (size_t)-1) { while (*p != '\0') { if (*p == '\\') *p = '/'; @@ -1887,6 +2700,8 @@ create_dir(struct archive_write_disk *a, char *path) if (mkdir(path, mode) == 0) { if (mode != mode_final) { le = new_fixup(a, path); + if (le == NULL) + return (ARCHIVE_FATAL); le->fixup |=TODO_MODE_BASE; le->mode = mode_final; } @@ -1979,6 +2794,7 @@ set_time(int fd, int mode, const char *name, * on fds and symlinks. */ struct timespec ts[2]; + (void)mode; /* UNUSED */ ts[0].tv_sec = atime; ts[0].tv_nsec = atime_nsec; ts[1].tv_sec = mtime; @@ -2036,6 +2852,11 @@ set_time(int fd, int mode, const char *name, /* * We don't know how to set the time on this platform. */ + (void)fd; /* UNUSED */ + (void)mode; /* UNUSED */ + (void)name; /* UNUSED */ + (void)atime_nsec; /* UNUSED */ + (void)mtime_nsec; /* UNUSED */ return (ARCHIVE_WARN); #endif } @@ -2068,7 +2889,7 @@ set_times(struct archive_write_disk *a, time_t atime, long atime_nanos, time_t birthtime, long birthtime_nanos, time_t mtime, long mtime_nanos, - time_t ctime, long ctime_nanos) + time_t cctime, long ctime_nanos) { /* Note: set_time doesn't use libarchive return conventions! * It uses syscall conventions. So 0 here instead of ARCHIVE_OK. */ @@ -2083,9 +2904,12 @@ set_times(struct archive_write_disk *a, if (a->user_uid == 0 && set_time_tru64(fd, mode, name, atime, atime_nanos, mtime, - mtime_nanos, ctime, ctime_nanos) == 0) { + mtime_nanos, cctime, ctime_nanos) == 0) { return (ARCHIVE_OK); } +#else /* Tru64 */ + (void)cctime; /* UNUSED */ + (void)ctime_nanos; /* UNUSED */ #endif /* Tru64 */ #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME @@ -2102,6 +2926,9 @@ set_times(struct archive_write_disk *a, r1 = set_time(fd, mode, name, atime, atime_nanos, birthtime, birthtime_nanos); +#else + (void)birthtime; /* UNUSED */ + (void)birthtime_nanos; /* UNUSED */ #endif r2 = set_time(fd, mode, name, atime, atime_nanos, @@ -2117,11 +2944,11 @@ set_times(struct archive_write_disk *a, static int set_times_from_entry(struct archive_write_disk *a) { - time_t atime, birthtime, mtime, ctime; + time_t atime, birthtime, mtime, cctime; long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec; /* Suitable defaults. */ - atime = birthtime = mtime = ctime = a->start_time; + atime = birthtime = mtime = cctime = a->start_time; atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0; /* If no time was provided, we're done. */ @@ -2145,7 +2972,7 @@ set_times_from_entry(struct archive_write_disk *a) mtime_nsec = archive_entry_mtime_nsec(a->entry); } if (archive_entry_ctime_is_set(a->entry)) { - ctime = archive_entry_ctime(a->entry); + cctime = archive_entry_ctime(a->entry); ctime_nsec = archive_entry_ctime_nsec(a->entry); } @@ -2153,7 +2980,7 @@ set_times_from_entry(struct archive_write_disk *a) atime, atime_nsec, birthtime, birthtime_nsec, mtime, mtime_nsec, - ctime, ctime_nsec); + cctime, ctime_nsec); } static int @@ -2312,6 +3139,8 @@ set_fflags(struct archive_write_disk *a) */ if ((critical_flags != 0) && (set & critical_flags)) { le = current_fixup(a, a->name); + if (le == NULL) + return (ARCHIVE_FATAL); le->fixup |= TODO_FFLAGS; le->fflags_set = set; /* Store the mode if it's not already there. */ @@ -2390,8 +3219,8 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, { int ret; int myfd = fd; - unsigned long newflags, oldflags; - unsigned long sf_mask = 0; + int newflags, oldflags; + int sf_mask = 0; if (set == 0 && clear == 0) return (ARCHIVE_OK); @@ -2400,8 +3229,10 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, return (ARCHIVE_OK); /* If we weren't given an fd, open it ourselves. */ - if (myfd < 0) - myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY); + if (myfd < 0) { + myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(myfd); + } if (myfd < 0) return (ARCHIVE_OK); @@ -2486,12 +3317,196 @@ set_mac_metadata(struct archive_write_disk *a, const char *pathname, (void)metadata_size; /* UNUSED */ return (ARCHIVE_OK); } + +static int +fixup_appledouble(struct archive_write_disk *a, const char *pathname) +{ + (void)a; /* UNUSED */ + (void)pathname; /* UNUSED */ + return (ARCHIVE_OK); +} #else /* * On Mac OS, we use copyfile() to unpack the metadata and * apply it to the target file. */ + +#if defined(HAVE_SYS_XATTR_H) +static int +copy_xattrs(struct archive_write_disk *a, int tmpfd, int dffd) +{ + ssize_t xattr_size; + char *xattr_names = NULL, *xattr_val = NULL; + int ret = ARCHIVE_OK, xattr_i; + + xattr_size = flistxattr(tmpfd, NULL, 0, 0); + if (xattr_size == -1) { + archive_set_error(&a->archive, errno, + "Failed to read metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + xattr_names = malloc(xattr_size); + if (xattr_names == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for metadata(xattr)"); + ret = ARCHIVE_FATAL; + goto exit_xattr; + } + xattr_size = flistxattr(tmpfd, xattr_names, xattr_size, 0); + if (xattr_size == -1) { + archive_set_error(&a->archive, errno, + "Failed to read metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + for (xattr_i = 0; xattr_i < xattr_size; + xattr_i += strlen(xattr_names + xattr_i) + 1) { + ssize_t s; + int f; + + s = fgetxattr(tmpfd, xattr_names + xattr_i, NULL, 0, 0, 0); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + xattr_val = realloc(xattr_val, s); + if (xattr_val == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + s = fgetxattr(tmpfd, xattr_names + xattr_i, xattr_val, s, 0, 0); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + f = fsetxattr(dffd, xattr_names + xattr_i, xattr_val, s, 0, 0); + if (f == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + } +exit_xattr: + free(xattr_names); + free(xattr_val); + return (ret); +} +#endif + +static int +copy_acls(struct archive_write_disk *a, int tmpfd, int dffd) +{ + acl_t acl, dfacl = NULL; + int acl_r, ret = ARCHIVE_OK; + + acl = acl_get_fd(tmpfd); + if (acl == NULL) { + if (errno == ENOENT) + /* There are not any ACLs. */ + return (ret); + archive_set_error(&a->archive, errno, + "Failed to get metadata(acl)"); + ret = ARCHIVE_WARN; + goto exit_acl; + } + dfacl = acl_dup(acl); + acl_r = acl_set_fd(dffd, dfacl); + if (acl_r == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(acl)"); + ret = ARCHIVE_WARN; + goto exit_acl; + } +exit_acl: + if (acl) + acl_free(acl); + if (dfacl) + acl_free(dfacl); + return (ret); +} + +static int +create_tempdatafork(struct archive_write_disk *a, const char *pathname) +{ + struct archive_string tmpdatafork; + int tmpfd; + + archive_string_init(&tmpdatafork); + archive_strcpy(&tmpdatafork, "tar.md.XXXXXX"); + tmpfd = mkstemp(tmpdatafork.s); + if (tmpfd < 0) { + archive_set_error(&a->archive, errno, + "Failed to mkstemp"); + archive_string_free(&tmpdatafork); + return (-1); + } + if (copyfile(pathname, tmpdatafork.s, 0, + COPYFILE_UNPACK | COPYFILE_NOFOLLOW + | COPYFILE_ACL | COPYFILE_XATTR) < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + close(tmpfd); + tmpfd = -1; + } + unlink(tmpdatafork.s); + archive_string_free(&tmpdatafork); + return (tmpfd); +} + +static int +copy_metadata(struct archive_write_disk *a, const char *metadata, + const char *datafork, int datafork_compressed) +{ + int ret = ARCHIVE_OK; + + if (datafork_compressed) { + int dffd, tmpfd; + + tmpfd = create_tempdatafork(a, metadata); + if (tmpfd == -1) + return (ARCHIVE_WARN); + + /* + * Do not open the data fork compressed by HFS+ compression + * with at least a writing mode(O_RDWR or O_WRONLY). it + * makes the data fork uncompressed. + */ + dffd = open(datafork, 0); + if (dffd == -1) { + archive_set_error(&a->archive, errno, + "Failed to open the data fork for metadata"); + close(tmpfd); + return (ARCHIVE_WARN); + } + +#if defined(HAVE_SYS_XATTR_H) + ret = copy_xattrs(a, tmpfd, dffd); + if (ret == ARCHIVE_OK) +#endif + ret = copy_acls(a, tmpfd, dffd); + close(tmpfd); + close(dffd); + } else { + if (copyfile(metadata, datafork, 0, + COPYFILE_UNPACK | COPYFILE_NOFOLLOW + | COPYFILE_ACL | COPYFILE_XATTR) < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + ret = ARCHIVE_WARN; + } + } + return (ret); +} + static int set_mac_metadata(struct archive_write_disk *a, const char *pathname, const void *metadata, size_t metadata_size) @@ -2513,139 +3528,101 @@ set_mac_metadata(struct archive_write_disk *a, const char *pathname, if (fd < 0) { archive_set_error(&a->archive, errno, "Failed to restore metadata"); + archive_string_free(&tmp); return (ARCHIVE_WARN); } written = write(fd, metadata, metadata_size); close(fd); - if (written != metadata_size - || copyfile(tmp.s, pathname, 0, - COPYFILE_UNPACK | COPYFILE_NOFOLLOW - | COPYFILE_ACL | COPYFILE_XATTR)) { + if ((size_t)written != metadata_size) { archive_set_error(&a->archive, errno, "Failed to restore metadata"); ret = ARCHIVE_WARN; + } else { + int compressed; + +#if defined(UF_COMPRESSED) + if ((a->todo & TODO_HFS_COMPRESSION) != 0 && + (ret = lazy_stat(a)) == ARCHIVE_OK) + compressed = a->st.st_flags & UF_COMPRESSED; + else +#endif + compressed = 0; + ret = copy_metadata(a, tmp.s, pathname, compressed); } unlink(tmp.s); + archive_string_free(&tmp); return (ret); } -#endif -#ifndef HAVE_POSIX_ACL -/* Default empty function body to satisfy mainline code. */ static int -set_acls(struct archive_write_disk *a, int fd, const char *name, - struct archive_acl *acl) +fixup_appledouble(struct archive_write_disk *a, const char *pathname) { - (void)a; /* UNUSED */ - (void)fd; /* UNUSED */ - (void)name; /* UNUSED */ - (void)acl; /* UNUSED */ - return (ARCHIVE_OK); -} - -#else - -/* - * XXX TODO: What about ACL types other than ACCESS and DEFAULT? - */ -static int -set_acls(struct archive_write_disk *a, int fd, const char *name, - struct archive_acl *abstract_acl) -{ - int ret; - - ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); - if (ret != ARCHIVE_OK) - return (ret); - ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); - return (ret); -} - - -static int -set_acl(struct archive_write_disk *a, int fd, const char *name, - struct archive_acl *abstract_acl, - acl_type_t acl_type, int ae_requested_type, const char *tname) -{ - acl_t acl; - acl_entry_t acl_entry; - acl_permset_t acl_permset; - int ret; - int ae_type, ae_permset, ae_tag, ae_id; - uid_t ae_uid; - gid_t ae_gid; - const char *ae_name; - int entries; + char buff[8]; + struct stat st; + const char *p; + struct archive_string datafork; + int fd = -1, ret = ARCHIVE_OK; + + archive_string_init(&datafork); + /* Check if the current file name is a type of the resource + * fork file. */ + p = strrchr(pathname, '/'); + if (p == NULL) + p = pathname; + else + p++; + if (p[0] != '.' || p[1] != '_') + goto skip_appledouble; - ret = ARCHIVE_OK; - entries = archive_acl_reset(abstract_acl, ae_requested_type); - if (entries == 0) - return (ARCHIVE_OK); - acl = acl_init(entries); - while (archive_acl_next(&a->archive, abstract_acl, - ae_requested_type, &ae_type, &ae_permset, &ae_tag, &ae_id, - &ae_name) == ARCHIVE_OK) { - acl_create_entry(&acl, &acl_entry); - - switch (ae_tag) { - case ARCHIVE_ENTRY_ACL_USER: - acl_set_tag_type(acl_entry, ACL_USER); - ae_uid = archive_write_disk_uid(&a->archive, - ae_name, ae_id); - acl_set_qualifier(acl_entry, &ae_uid); - break; - case ARCHIVE_ENTRY_ACL_GROUP: - acl_set_tag_type(acl_entry, ACL_GROUP); - ae_gid = archive_write_disk_gid(&a->archive, - ae_name, ae_id); - acl_set_qualifier(acl_entry, &ae_gid); - break; - case ARCHIVE_ENTRY_ACL_USER_OBJ: - acl_set_tag_type(acl_entry, ACL_USER_OBJ); - break; - case ARCHIVE_ENTRY_ACL_GROUP_OBJ: - acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); - break; - case ARCHIVE_ENTRY_ACL_MASK: - acl_set_tag_type(acl_entry, ACL_MASK); - break; - case ARCHIVE_ENTRY_ACL_OTHER: - acl_set_tag_type(acl_entry, ACL_OTHER); - break; - default: - /* XXX */ - break; - } + /* + * Check if the data fork file exists. + * + * TODO: Check if this write disk object has handled it. + */ + archive_strncpy(&datafork, pathname, p - pathname); + archive_strcat(&datafork, p + 2); + if (lstat(datafork.s, &st) == -1 || + (st.st_mode & AE_IFMT) != AE_IFREG) + goto skip_appledouble; - acl_get_permset(acl_entry, &acl_permset); - acl_clear_perms(acl_permset); - if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE) - acl_add_perm(acl_permset, ACL_EXECUTE); - if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE) - acl_add_perm(acl_permset, ACL_WRITE); - if (ae_permset & ARCHIVE_ENTRY_ACL_READ) - acl_add_perm(acl_permset, ACL_READ); + /* + * Check if the file is in the AppleDouble form. + */ + fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); + if (fd == -1) { + archive_set_error(&a->archive, errno, + "Failed to open a restoring file"); + ret = ARCHIVE_WARN; + goto skip_appledouble; } - - /* Try restoring the ACL through 'fd' if we can. */ -#if HAVE_ACL_SET_FD - if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0) - ret = ARCHIVE_OK; - else + if (read(fd, buff, 8) == -1) { + archive_set_error(&a->archive, errno, + "Failed to read a restoring file"); + close(fd); + ret = ARCHIVE_WARN; + goto skip_appledouble; + } + close(fd); + /* Check AppleDouble Magic Code. */ + if (archive_be32dec(buff) != 0x00051607) + goto skip_appledouble; + /* Check AppleDouble Version. */ + if (archive_be32dec(buff+4) != 0x00020000) + goto skip_appledouble; + + ret = copy_metadata(a, pathname, datafork.s, +#if defined(UF_COMPRESSED) + st.st_flags & UF_COMPRESSED); #else -#if HAVE_ACL_SET_FD_NP - if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0) - ret = ARCHIVE_OK; - else -#endif + 0); #endif - if (acl_set_file(name, acl_type, acl) != 0) { - archive_set_error(&a->archive, errno, "Failed to set %s acl", tname); - ret = ARCHIVE_WARN; + if (ret == ARCHIVE_OK) { + unlink(pathname); + ret = ARCHIVE_EOF; } - acl_free(acl); +skip_appledouble: + archive_string_free(&datafork); return (ret); } #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h b/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h index 707c0cf03..d84e7e1cd 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h @@ -33,6 +33,11 @@ #ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED #define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED +#include "archive_acl_private.h" + struct archive_write_disk; +int +archive_write_disk_set_acls(struct archive *, int /* fd */, const char * /* pathname */, struct archive_acl *); + #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c index 5ee89a79a..e79008ef6 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c @@ -122,6 +122,7 @@ lookup_gid(void *private_data, const char *gname, int64_t gid) char _buffer[128]; size_t bufsize = 128; char *buffer = _buffer; + char *allocated = NULL; struct group grent, *result; int r; @@ -133,16 +134,15 @@ lookup_gid(void *private_data, const char *gname, int64_t gid) if (r != ERANGE) break; bufsize *= 2; - if (buffer != _buffer) - free(buffer); - buffer = malloc(bufsize); - if (buffer == NULL) + free(allocated); + allocated = malloc(bufsize); + if (allocated == NULL) break; + buffer = allocated; } if (result != NULL) gid = result->gr_gid; - if (buffer != _buffer) - free(buffer); + free(allocated); } # else /* HAVE_GETGRNAM_R */ { @@ -158,7 +158,7 @@ lookup_gid(void *private_data, const char *gname, int64_t gid) #else #error No way to perform gid lookups on this platform #endif - b->id = gid; + b->id = (gid_t)gid; return (gid); } @@ -192,6 +192,7 @@ lookup_uid(void *private_data, const char *uname, int64_t uid) char _buffer[128]; size_t bufsize = 128; char *buffer = _buffer; + char *allocated = NULL; struct passwd pwent, *result; int r; @@ -203,16 +204,15 @@ lookup_uid(void *private_data, const char *uname, int64_t uid) if (r != ERANGE) break; bufsize *= 2; - if (buffer != _buffer) - free(buffer); - buffer = malloc(bufsize); - if (buffer == NULL) + free(allocated); + allocated = malloc(bufsize); + if (allocated == NULL) break; + buffer = allocated; } if (result != NULL) uid = result->pw_uid; - if (buffer != _buffer) - free(buffer); + free(allocated); } # else /* HAVE_GETPWNAM_R */ { @@ -228,7 +228,7 @@ lookup_uid(void *private_data, const char *uname, int64_t uid) #else #error No way to look up uids on this platform #endif - b->id = uid; + b->id = (uid_t)uid; return (uid); } diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c index 2dc2d92e8..0f0780a8e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2010 Tim Kientzle - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,9 +33,6 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif #ifdef HAVE_SYS_UTIME_H #include <sys/utime.h> #endif @@ -48,13 +45,9 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_LIMITS_H #include <limits.h> #endif -#include <stdio.h> #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif #include <winioctl.h> /* TODO: Support Mac OS 'quarantine' feature. This is really just a @@ -89,7 +82,7 @@ static BOOL SetFilePointerEx_perso(HANDLE hFile, if(lpNewFilePointer) { lpNewFilePointer->QuadPart = li.QuadPart; } - return li.LowPart != -1 || GetLastError() == NO_ERROR; + return li.LowPart != (DWORD)-1 || GetLastError() == NO_ERROR; } struct fixup_entry { @@ -144,8 +137,8 @@ struct archive_write_disk { struct fixup_entry *current_fixup; int64_t user_uid; int skip_file_set; - dev_t skip_file_dev; - ino_t skip_file_ino; + int64_t skip_file_dev; + int64_t skip_file_ino; time_t start_time; int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid); @@ -214,26 +207,24 @@ struct archive_write_disk { static int check_symlinks(struct archive_write_disk *); static int create_filesystem_object(struct archive_write_disk *); -static struct fixup_entry *current_fixup(struct archive_write_disk *, const wchar_t *pathname); -#if defined(HAVE_FCHDIR) && defined(PATH_MAX) -static void edit_deep_directories(struct archive_write_disk *ad); -#endif +static struct fixup_entry *current_fixup(struct archive_write_disk *, + const wchar_t *pathname); static int cleanup_pathname(struct archive_write_disk *); static int create_dir(struct archive_write_disk *, wchar_t *); static int create_parent_dir(struct archive_write_disk *, wchar_t *); +static int la_chmod(const wchar_t *, mode_t); static int older(BY_HANDLE_FILE_INFORMATION *, struct archive_entry *); +static int permissive_name_w(struct archive_write_disk *); static int restore_entry(struct archive_write_disk *); -#ifdef HAVE_POSIX_ACL -static int set_acl(struct archive_write_disk *, int fd, const char *, struct archive_acl *, - acl_type_t, int archive_entry_acl_type, const char *tn); -#endif -static int set_acls(struct archive_write_disk *, HANDLE h, const wchar_t *, struct archive_acl *); +static int set_acls(struct archive_write_disk *, HANDLE h, + const wchar_t *, struct archive_acl *); static int set_xattrs(struct archive_write_disk *); static int set_fflags(struct archive_write_disk *); static int set_ownership(struct archive_write_disk *); static int set_mode(struct archive_write_disk *, int mode); -static int set_times(struct archive_write_disk *, HANDLE, int, const wchar_t *, - time_t, long, time_t, long, time_t, long, time_t, long); +static int set_times(struct archive_write_disk *, HANDLE, int, + const wchar_t *, time_t, long, time_t, long, time_t, + long, time_t, long); static int set_times_from_entry(struct archive_write_disk *); static struct fixup_entry *sort_dir_list(struct fixup_entry *p); static ssize_t write_data_block(struct archive_write_disk *, @@ -243,11 +234,14 @@ static struct archive_vtable *archive_write_disk_vtable(void); static int _archive_write_disk_close(struct archive *); static int _archive_write_disk_free(struct archive *); -static int _archive_write_disk_header(struct archive *, struct archive_entry *); +static int _archive_write_disk_header(struct archive *, + struct archive_entry *); static int64_t _archive_write_disk_filter_bytes(struct archive *, int); static int _archive_write_disk_finish_entry(struct archive *); -static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t); -static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t); +static ssize_t _archive_write_disk_data(struct archive *, const void *, + size_t); +static ssize_t _archive_write_disk_data_block(struct archive *, const void *, + size_t, int64_t); #define bhfi_dev(bhfi) ((bhfi)->dwVolumeSerialNumber) /* Treat FileIndex as i-node. We should remove a sequence number @@ -361,7 +355,7 @@ file_information(struct archive_write_disk *a, wchar_t *path, * So we have to make the full-pathname in another way, which does not * break "../" path string. */ -int +static int permissive_name_w(struct archive_write_disk *a) { wchar_t *wn, *wnp; @@ -424,10 +418,12 @@ permissive_name_w(struct archive_write_disk *a) wn = _wcsdup(wnp); if (wn == NULL) return (-1); - archive_wstring_ensure(&(a->_name_data), 8 + wcslen(wn) + 1); + archive_wstring_ensure(&(a->_name_data), + 8 + wcslen(wn) + 1); a->name = a->_name_data.s; /* Prepend "\\?\UNC\" */ - archive_wstrncpy(&(a->_name_data), L"\\\\?\\UNC\\", 8); + archive_wstrncpy(&(a->_name_data), + L"\\\\?\\UNC\\", 8); archive_wstrcat(&(a->_name_data), wn+2); free(wn); return (0); @@ -457,7 +453,8 @@ permissive_name_w(struct archive_write_disk *a) wn = _wcsdup(wnp); if (wn == NULL) return (-1); - archive_wstring_ensure(&(a->_name_data), 4 + 2 + wcslen(wn) + 1); + archive_wstring_ensure(&(a->_name_data), + 4 + 2 + wcslen(wn) + 1); a->name = a->_name_data.s; /* Prepend "\\?\" and drive name. */ archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4); @@ -484,7 +481,7 @@ permissive_name_w(struct archive_write_disk *a) return (0); } -int +static int la_chmod(const wchar_t *path, mode_t mode) { DWORD attr; @@ -610,7 +607,7 @@ lazy_stat(struct archive_write_disk *a) /* * XXX At this point, symlinks should not be hit, otherwise - * XXX a race occured. Do we want to check explicitly for that? + * XXX a race occurred. Do we want to check explicitly for that? */ if (file_information(a, a->name, &a->st, NULL, 1) == 0) { a->pst = &a->st; @@ -917,6 +914,7 @@ archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i) static ssize_t write_data_block(struct archive_write_disk *a, const char *buff, size_t size) { + OVERLAPPED ol; uint64_t start_size = size; DWORD bytes_written = 0; ssize_t block_size = 0, bytes_to_write; @@ -968,26 +966,13 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size) * truncate it to the block boundary. */ bytes_to_write = size; if (a->offset + bytes_to_write > block_end) - bytes_to_write = block_end - a->offset; + bytes_to_write = (DWORD)(block_end - a->offset); } - /* Seek if necessary to the specified offset. */ - if (a->offset != a->fd_offset) { - LARGE_INTEGER distance; - distance.QuadPart = a->offset; - if (SetFilePointerEx_perso(a->fh, distance, NULL, FILE_BEGIN) == 0) { - DWORD lasterr = GetLastError(); - if (lasterr == ERROR_ACCESS_DENIED) - errno = EBADF; - else - la_dosmaperr(lasterr); - archive_set_error(&a->archive, errno, - "Seek failed"); - return (ARCHIVE_FATAL); - } - a->fd_offset = a->offset; - } + memset(&ol, 0, sizeof(ol)); + ol.Offset = (DWORD)(a->offset & 0xFFFFFFFF); + ol.OffsetHigh = (DWORD)(a->offset >> 32); if (!WriteFile(a->fh, buff, (uint32_t)bytes_to_write, - &bytes_written, NULL)) { + &bytes_written, &ol)) { DWORD lasterr; lasterr = GetLastError(); @@ -1004,7 +989,7 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size) a->offset += bytes_written; a->fd_offset = a->offset; } - return (start_size - size); + return ((ssize_t)(start_size - size)); } static ssize_t @@ -1062,48 +1047,11 @@ _archive_write_disk_finish_entry(struct archive *_a) /* Last write ended at exactly the filesize; we're done. */ /* Hopefully, this is the common case. */ } else { - if (la_ftruncate(a->fh, a->filesize) == -1 && - a->filesize == 0) { + if (la_ftruncate(a->fh, a->filesize) == -1) { archive_set_error(&a->archive, errno, "File size could not be restored"); return (ARCHIVE_FAILED); } - /* - * Not all platforms implement the XSI option to - * extend files via ftruncate. Stat() the file again - * to see what happened. - */ - a->pst = NULL; - if ((ret = lazy_stat(a)) != ARCHIVE_OK) - return (ret); - /* We can use lseek()/write() to extend the file if - * ftruncate didn't work or isn't available. */ - if (bhfi_size(&(a->st)) < a->filesize) { - const char nul = '\0'; - LARGE_INTEGER distance; - distance.QuadPart = a->filesize - 1; - if (!SetFilePointerEx_perso(a->fh, distance, NULL, FILE_BEGIN)) { - DWORD lasterr = GetLastError(); - if (lasterr == ERROR_ACCESS_DENIED) - errno = EBADF; - else - la_dosmaperr(lasterr); - archive_set_error(&a->archive, errno, - "Seek failed"); - return (ARCHIVE_FATAL); - } - if (!WriteFile(a->fh, &nul, 1, NULL, NULL)) { - DWORD lasterr = GetLastError(); - if (lasterr == ERROR_ACCESS_DENIED) - errno = EBADF; - else - la_dosmaperr(lasterr); - archive_set_error(&a->archive, errno, - "Write to restore size failed"); - return (ARCHIVE_FATAL); - } - a->pst = NULL; - } } /* Restore metadata. */ @@ -1430,7 +1378,8 @@ restore_entry(struct archive_write_disk *a) if (a->skip_file_set && bhfi_dev(&a->st) == a->skip_file_dev && bhfi_ino(&a->st) == a->skip_file_ino) { - archive_set_error(&a->archive, 0, "Refusing to overwrite archive"); + archive_set_error(&a->archive, 0, + "Refusing to overwrite archive"); return (ARCHIVE_FAILED); } @@ -1471,7 +1420,7 @@ restore_entry(struct archive_write_disk *a) if (en) { /* Everything failed; give up here. */ - archive_set_error(&a->archive, en, "Can't create '%s'", + archive_set_error(&a->archive, en, "Can't create '%ls'", a->name); return (ARCHIVE_FAILED); } @@ -1520,7 +1469,7 @@ create_filesystem_object(struct archive_write_disk *a) * * If the hardlink was successfully created and * the archive doesn't have carry data for it, - * consider it to be non-authoritive for meta data. + * consider it to be non-authoritative for meta data. * This is consistent with GNU tar and BSD pax. * If the hardlink does carry data, let the last * archive entry decide ownership. @@ -1562,7 +1511,7 @@ create_filesystem_object(struct archive_write_disk *a) * that SUID, SGID, etc, require additional work to ensure * security, so we never restore them at this point. */ - mode = final_mode & 0777 & a->user_umask; + mode = final_mode & 0777 & ~a->user_umask; switch (a->mode & AE_IFMT) { default: @@ -1881,7 +1830,7 @@ check_symlinks(struct archive_write_disk *a) */ if (disk_unlink(a->name)) { archive_set_error(&a->archive, errno, - "Could not remove symlink %s", + "Could not remove symlink %ls", a->name); pn[0] = c; return (ARCHIVE_FAILED); @@ -1895,7 +1844,7 @@ check_symlinks(struct archive_write_disk *a) */ if (!S_ISLNK(a->mode)) { archive_set_error(&a->archive, 0, - "Removing symlink %s", + "Removing symlink %ls", a->name); } /* Symlink gone. No more problem! */ @@ -1905,15 +1854,15 @@ check_symlinks(struct archive_write_disk *a) /* User asked us to remove problems. */ if (disk_unlink(a->name) != 0) { archive_set_error(&a->archive, 0, - "Cannot remove intervening symlink %s", - a->name); + "Cannot remove intervening " + "symlink %ls", a->name); pn[0] = c; return (ARCHIVE_FAILED); } a->pst = NULL; } else { archive_set_error(&a->archive, 0, - "Cannot extract through symlink %s", + "Cannot extract through symlink %ls", a->name); pn[0] = c; return (ARCHIVE_FAILED); @@ -2184,19 +2133,20 @@ create_dir(struct archive_write_disk *a, wchar_t *path) return (ARCHIVE_OK); if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { archive_set_error(&a->archive, EEXIST, - "Can't create directory '%s'", path); + "Can't create directory '%ls'", path); return (ARCHIVE_FAILED); } if (disk_unlink(path) != 0) { archive_set_error(&a->archive, errno, - "Can't create directory '%s': " + "Can't create directory '%ls': " "Conflicting file cannot be removed", path); return (ARCHIVE_FAILED); } } else if (errno != ENOENT && errno != ENOTDIR) { /* Stat failed? */ - archive_set_error(&a->archive, errno, "Can't test directory '%s'", path); + archive_set_error(&a->archive, errno, + "Can't test directory '%ls'", path); return (ARCHIVE_FAILED); } else if (slash != NULL) { *slash = '\0'; @@ -2245,10 +2195,11 @@ create_dir(struct archive_write_disk *a, wchar_t *path) * don't add it to the fixup list here, as it's already been * added. */ - if (file_information(a, path, &st, &st_mode, 0) == 0 && S_ISDIR(st_mode)) + if (file_information(a, path, &st, &st_mode, 0) == 0 && + S_ISDIR(st_mode)) return (ARCHIVE_OK); - archive_set_error(&a->archive, errno, "Failed to create dir '%s'", + archive_set_error(&a->archive, errno, "Failed to create dir '%ls'", path); return (ARCHIVE_FAILED); } @@ -2277,7 +2228,7 @@ set_ownership(struct archive_write_disk *a) } archive_set_error(&a->archive, errno, - "Can't set user=%jd/group=%jd for %s", + "Can't set user=%jd/group=%jd for %ls", (intmax_t)a->uid, (intmax_t)a->gid, a->name); return (ARCHIVE_WARN); } @@ -2288,7 +2239,7 @@ set_times(struct archive_write_disk *a, time_t atime, long atime_nanos, time_t birthtime, long birthtime_nanos, time_t mtime, long mtime_nanos, - time_t ctime, long ctime_nanos) + time_t ctime_sec, long ctime_nanos) { #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) #define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\ @@ -2299,7 +2250,7 @@ set_times(struct archive_write_disk *a, FILETIME *pfbtime; FILETIME fatime, fbtime, fmtime; - (void)ctime; /* UNUSED */ + (void)ctime_sec; /* UNUSED */ (void)ctime_nanos; /* UNUSED */ if (h != INVALID_HANDLE_VALUE) { @@ -2350,11 +2301,11 @@ settimes_failed: static int set_times_from_entry(struct archive_write_disk *a) { - time_t atime, birthtime, mtime, ctime; + time_t atime, birthtime, mtime, ctime_sec; long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec; /* Suitable defaults. */ - atime = birthtime = mtime = ctime = a->start_time; + atime = birthtime = mtime = ctime_sec = a->start_time; atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0; /* If no time was provided, we're done. */ @@ -2376,7 +2327,7 @@ set_times_from_entry(struct archive_write_disk *a) mtime_nsec = archive_entry_mtime_nsec(a->entry); } if (archive_entry_ctime_is_set(a->entry)) { - ctime = archive_entry_ctime(a->entry); + ctime_sec = archive_entry_ctime(a->entry); ctime_nsec = archive_entry_ctime_nsec(a->entry); } @@ -2384,7 +2335,7 @@ set_times_from_entry(struct archive_write_disk *a) atime, atime_nsec, birthtime, birthtime_nsec, mtime, mtime_nsec, - ctime, ctime_nsec); + ctime_sec, ctime_nsec); } static int @@ -2507,7 +2458,7 @@ set_xattrs(struct archive_write_disk *a) } static void -fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns) +fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns) { ULARGE_INTEGER utc; @@ -2516,11 +2467,11 @@ fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns) if (utc.QuadPart >= EPOC_TIME) { utc.QuadPart -= EPOC_TIME; /* milli seconds base */ - *time = (time_t)(utc.QuadPart / 10000000); + *t = (time_t)(utc.QuadPart / 10000000); /* nano seconds base */ *ns = (long)(utc.QuadPart % 10000000) * 100; } else { - *time = 0; + *t = 0; *ns = 0; } } diff --git a/Utilities/cmlibarchive/libarchive/archive_write_filter.3 b/Utilities/cmlibarchive/libarchive/archive_write_filter.3 index 00438d405..3ca248b72 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_filter.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_filter.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 23, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_WRITE_FILTER 3 .Os .Sh NAME @@ -36,6 +36,8 @@ .Nm archive_write_add_filter_none , .Nm archive_write_add_filter_program , .Nm archive_write_add_filter_xz +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3 b/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3 index 3add60129..d881c80ea 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3 @@ -22,14 +22,16 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $ +.\" $FreeBSD$ .\" -.Dd March 23, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_WRITE_FINISH_ENTRY 3 .Os .Sh NAME .Nm archive_write_finish_entry .Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_write_format.3 b/Utilities/cmlibarchive/libarchive/archive_write_format.3 index e12e7d865..dad2f7d7e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_format.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_format.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 23, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_WRITE_FORMAT 3 .Os .Sh NAME @@ -35,6 +35,8 @@ .Nm archive_write_set_format_shar_dump , .Nm archive_write_set_format_ustar .Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_write_free.3 b/Utilities/cmlibarchive/libarchive/archive_write_free.3 index 27efe18b0..1b2d07131 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_free.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_free.3 @@ -24,17 +24,22 @@ .\" .\" $FreeBSD$ .\" -.Dd March 23, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_WRITE_FREE 3 .Os .Sh NAME +.Nm archive_write_fail , .Nm archive_write_close , .Nm archive_write_finish , .Nm archive_write_free .Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int +.Fn archive_write_fail "struct archive *" +.Ft int .Fn archive_write_close "struct archive *" .Ft int .Fn archive_write_finish "struct archive *" @@ -42,6 +47,16 @@ .Fn archive_write_free "struct archive *" .Sh DESCRIPTION .Bl -tag -width indent +.It Fn archive_write_fail +Always returns +.Cm ARCHIVE_FATAL . +This marks the archive object as being unusable; +after calling this function, the only call that can succeed is +.Fn archive_write_free +to release the resources. +This can be used to speed recovery when the archive creation +must be aborted. +Note that the created archive is likely to be malformed in this case; .It Fn archive_write_close Complete the archive and invoke the close callback. .It Fn archive_write_finish diff --git a/Utilities/cmlibarchive/libarchive/archive_write_header.3 b/Utilities/cmlibarchive/libarchive/archive_write_header.3 index 423b38e46..4de58f3b9 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_header.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_header.3 @@ -24,12 +24,14 @@ .\" .\" $FreeBSD$ .\" -.Dd March 23, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_WRITE_HEADER 3 .Os .Sh NAME .Nm archive_write_header .Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_write_new.3 b/Utilities/cmlibarchive/libarchive/archive_write_new.3 index d626ccb73..f05d269d3 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_new.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_new.3 @@ -24,12 +24,14 @@ .\" .\" $FreeBSD$ .\" -.Dd March 23, 2011 +.Dd February 2, 2012 .Dt ARCHIVE_WRITE_NEW 3 .Os .Sh NAME .Nm archive_write_new .Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft struct archive * diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open.3 b/Utilities/cmlibarchive/libarchive/archive_write_open.3 index 0d12cb3b3..4037248e0 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_open.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_open.3 @@ -22,10 +22,10 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $ +.\" $FreeBSD$ .\" -.Dd March 23, 2011 -.Dt ARCHIVE_WRITE 3 +.Dd February 2, 2012 +.Dt ARCHIVE_WRITE_OPEN 3 .Os .Sh NAME .Nm archive_write_open , @@ -34,6 +34,8 @@ .Nm archive_write_open_filename , .Nm archive_write_open_memory .Nd functions for creating archives +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .In archive.h .Ft int diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c b/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c index 868986631..196b770e8 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c @@ -46,24 +46,25 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_open_filename.c 191165 200 #endif #include "archive.h" +#include "archive_private.h" #include "archive_string.h" #ifndef O_BINARY #define O_BINARY 0 #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif struct write_file_data { int fd; - char mbs_filename; - union { - char m[1]; - wchar_t w[1]; - } filename; /* Must be last! */ + struct archive_mstring filename; }; static int file_close(struct archive *, void *); static int file_open(struct archive *, void *); static ssize_t file_write(struct archive *, void *, const void *buff, size_t); +static int open_filename(struct archive *, int, const void *); int archive_write_open_file(struct archive *a, const char *filename) @@ -74,123 +75,122 @@ archive_write_open_file(struct archive *a, const char *filename) int archive_write_open_filename(struct archive *a, const char *filename) { - struct write_file_data *mine; if (filename == NULL || filename[0] == '\0') return (archive_write_open_fd(a, 1)); - mine = (struct write_file_data *)malloc(sizeof(*mine) + strlen(filename)); - if (mine == NULL) { - archive_set_error(a, ENOMEM, "No memory"); - return (ARCHIVE_FATAL); - } - strcpy(mine->filename.m, filename); - mine->mbs_filename = 1; - mine->fd = -1; - return (archive_write_open(a, mine, - file_open, file_write, file_close)); + return (open_filename(a, 1, filename)); } int archive_write_open_filename_w(struct archive *a, const wchar_t *filename) { -#if defined(_WIN32) && !defined(__CYGWIN__) - struct write_file_data *mine; if (filename == NULL || filename[0] == L'\0') return (archive_write_open_fd(a, 1)); - mine = malloc(sizeof(*mine) + wcslen(filename) * sizeof(wchar_t)); + return (open_filename(a, 0, filename)); +} + +static int +open_filename(struct archive *a, int mbs_fn, const void *filename) +{ + struct write_file_data *mine; + int r; + + mine = (struct write_file_data *)calloc(1, sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } - wcscpy(mine->filename.w, filename); - mine->mbs_filename = 0; + if (mbs_fn) + r = archive_mstring_copy_mbs(&mine->filename, filename); + else + r = archive_mstring_copy_wcs(&mine->filename, filename); + if (r < 0) { + if (errno == ENOMEM) { + archive_set_error(a, ENOMEM, "No memory"); + return (ARCHIVE_FATAL); + } + if (mbs_fn) + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Can't convert '%s' to WCS", + (const char *)filename); + else + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Can't convert '%S' to MBS", + (const wchar_t *)filename); + return (ARCHIVE_FAILED); + } mine->fd = -1; return (archive_write_open(a, mine, file_open, file_write, file_close)); -#else - /* - * POSIX system does not support a wchar_t interface for - * open() system call, so we have to translate a wchar_t - * filename to multi-byte one and use it. - */ - struct archive_string fn; - int r; - - if (filename == NULL || filename[0] == L'\0') - return (archive_write_open_fd(a, 1)); - - archive_string_init(&fn); - if (archive_string_append_from_wcs(&fn, filename, - wcslen(filename)) != 0) { - archive_set_error(a, EINVAL, - "Failed to convert a wide-character filename to" - " a multi-byte filename"); - archive_string_free(&fn); - return (ARCHIVE_FATAL); - } - r = archive_write_open_filename(a, fn.s); - archive_string_free(&fn); - return (r); -#endif } - static int file_open(struct archive *a, void *client_data) { int flags; struct write_file_data *mine; struct stat st; +#if defined(_WIN32) && !defined(__CYGWIN__) + wchar_t *fullpath; +#endif + const wchar_t *wcs; + const char *mbs; mine = (struct write_file_data *)client_data; - flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; + flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC; /* * Open the file. */ - if (mine->mbs_filename) { - mine->fd = open(mine->filename.m, flags, 0666); - if (mine->fd < 0) { - archive_set_error(a, errno, "Failed to open '%s'", - mine->filename.m); - return (ARCHIVE_FATAL); - } - - if (fstat(mine->fd, &st) != 0) { - archive_set_error(a, errno, "Couldn't stat '%s'", - mine->filename.m); - return (ARCHIVE_FATAL); - } - } else { + mbs = NULL; wcs = NULL; #if defined(_WIN32) && !defined(__CYGWIN__) - mine->fd = _wopen(mine->filename.w, flags, 0666); - if (mine->fd < 0 && errno == ENOENT) { - wchar_t *fullpath; - fullpath = __la_win_permissive_name_w(mine->filename.w); - if (fullpath != NULL) { - mine->fd = _wopen(fullpath, flags, 0666); - free(fullpath); - } - } - if (mine->fd < 0) { - archive_set_error(a, errno, "Failed to open '%S'", - mine->filename.w); - return (ARCHIVE_FATAL); - } - - if (fstat(mine->fd, &st) != 0) { - archive_set_error(a, errno, "Couldn't stat '%S'", - mine->filename.w); - return (ARCHIVE_FATAL); + if (archive_mstring_get_wcs(a, &mine->filename, &wcs) != 0) { + if (errno == ENOMEM) + archive_set_error(a, errno, "No memory"); + else { + archive_mstring_get_mbs(a, &mine->filename, &mbs); + archive_set_error(a, errno, + "Can't convert '%s' to WCS", mbs); } + return (ARCHIVE_FATAL); + } + fullpath = __la_win_permissive_name_w(wcs); + if (fullpath != NULL) { + mine->fd = _wopen(fullpath, flags, 0666); + free(fullpath); + } else + mine->fd = _wopen(wcs, flags, 0666); #else - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Unexpedted operation in archive_write_open_filename"); + if (archive_mstring_get_mbs(a, &mine->filename, &mbs) != 0) { + if (errno == ENOMEM) + archive_set_error(a, errno, "No memory"); + else { + archive_mstring_get_wcs(a, &mine->filename, &wcs); + archive_set_error(a, errno, + "Can't convert '%S' to MBS", wcs); + } return (ARCHIVE_FATAL); + } + mine->fd = open(mbs, flags, 0666); + __archive_ensure_cloexec_flag(mine->fd); #endif + if (mine->fd < 0) { + if (mbs != NULL) + archive_set_error(a, errno, "Failed to open '%s'", mbs); + else + archive_set_error(a, errno, "Failed to open '%S'", wcs); + return (ARCHIVE_FATAL); + } + + if (fstat(mine->fd, &st) != 0) { + if (mbs != NULL) + archive_set_error(a, errno, "Couldn't stat '%s'", mbs); + else + archive_set_error(a, errno, "Couldn't stat '%S'", wcs); + return (ARCHIVE_FATAL); } /* @@ -218,7 +218,8 @@ file_open(struct archive *a, void *client_data) } static ssize_t -file_write(struct archive *a, void *client_data, const void *buff, size_t length) +file_write(struct archive *a, void *client_data, const void *buff, + size_t length) { struct write_file_data *mine; ssize_t bytesWritten; @@ -243,6 +244,7 @@ file_close(struct archive *a, void *client_data) (void)a; /* UNUSED */ close(mine->fd); + archive_mstring_clean(&mine->filename); free(mine); return (ARCHIVE_OK); } diff --git a/Utilities/cmlibarchive/libarchive/archive_write_private.h b/Utilities/cmlibarchive/libarchive/archive_write_private.h index 91284cf1b..e600d5474 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_write_private.h @@ -72,7 +72,7 @@ struct archive_write { /* Dev/ino of the archive being written. */ int skip_file_set; - dev_t skip_file_dev; + int64_t skip_file_dev; int64_t skip_file_ino; /* Utility: Pointer to a block of nulls. */ @@ -133,4 +133,13 @@ __archive_write_format_header_ustar(struct archive_write *, char buff[512], struct archive_entry *, int tartype, int strict, struct archive_string_conv *); +struct archive_write_program_data; +struct archive_write_program_data * __archive_write_program_allocate(void); +int __archive_write_program_free(struct archive_write_program_data *); +int __archive_write_program_open(struct archive_write_filter *, + struct archive_write_program_data *, const char *); +int __archive_write_program_close(struct archive_write_filter *, + struct archive_write_program_data *); +int __archive_write_program_write(struct archive_write_filter *, + struct archive_write_program_data *, const void *, size_t); #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c index 5bb248c55..4f1bc2622 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -199,7 +199,7 @@ struct _7zip { /* * Compressed data buffer. */ - unsigned char wbuff[1024 * 64]; + unsigned char wbuff[512 * 20 * 6]; size_t wbuff_remaining; /* @@ -385,7 +385,7 @@ _7z_options(struct archive_write *a, const char *key, const char *value) else { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "Unkonwn compression name: `%s'", + "Unknown compression name: `%s'", value); return (ARCHIVE_FAILED); } @@ -405,7 +405,7 @@ _7z_options(struct archive_write *a, const char *key, const char *value) value[1] != '\0') { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "Illeagal value `%s'", + "Illegal value `%s'", value); return (ARCHIVE_FAILED); } @@ -413,7 +413,10 @@ _7z_options(struct archive_write *a, const char *key, const char *value) return (ARCHIVE_OK); } - return (ARCHIVE_FAILED); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -439,6 +442,14 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry) file_free(file); return (r); } + if (file->size == 0 && file->dir) { + if (!__archive_rb_tree_insert_node(&(zip->rbtree), + (struct archive_rb_node *)file)) { + /* We have already had the same file. */ + file_free(file); + return (ARCHIVE_OK); + } + } if (file->flg & MTIME_IS_SET) zip->total_number_time_defined[MTIME]++; @@ -447,11 +458,6 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry) if (file->flg & ATIME_IS_SET) zip->total_number_time_defined[ATIME]++; - if (file->size == 0 && file->dir) { - if (!__archive_rb_tree_insert_node(&(zip->rbtree), - (struct archive_rb_node *)file)) - file_free(file); - } zip->total_number_entry++; zip->total_bytes_entry_name += file->name_len + 2; if (file->size == 0) { @@ -495,10 +501,10 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry) if (archive_entry_filetype(entry) == AE_IFLNK) { ssize_t bytes; const void *p = (const void *)archive_entry_symlink(entry); - bytes = compress_out(a, p, file->size, ARCHIVE_Z_RUN); + bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN); if (bytes < 0) return ((int)bytes); - zip->entry_crc32 = crc32(zip->entry_crc32, p, bytes); + zip->entry_crc32 = crc32(zip->entry_crc32, p, (unsigned)bytes); zip->entry_bytes_remaining -= bytes; } @@ -512,7 +518,7 @@ static int write_to_temp(struct archive_write *a, const void *buff, size_t s) { struct _7zip *zip; - unsigned char *p; + const unsigned char *p; ssize_t ws; zip = (struct _7zip *)a->format_data; @@ -530,7 +536,7 @@ write_to_temp(struct archive_write *a, const void *buff, size_t s) } } - p = (unsigned char *)buff; + p = (const unsigned char *)buff; while (s) { ws = write(zip->temp_fd, p, s); if (ws < 0) { @@ -556,10 +562,11 @@ compress_out(struct archive_write *a, const void *buff, size_t s, return (0); if ((zip->crc32flg & PRECODE_CRC32) && s) - zip->precode_crc32 = crc32(zip->precode_crc32, buff, s); + zip->precode_crc32 = crc32(zip->precode_crc32, buff, + (unsigned)s); zip->stream.next_in = (const unsigned char *)buff; zip->stream.avail_in = s; - do { + for (;;) { /* Compress file data. */ r = compression_code(&(a->archive), &(zip->stream), run); if (r != ARCHIVE_OK && r != ARCHIVE_EOF) @@ -573,15 +580,19 @@ compress_out(struct archive_write *a, const void *buff, size_t s, if (zip->crc32flg & ENCODED_CRC32) zip->encoded_crc32 = crc32(zip->encoded_crc32, zip->wbuff, sizeof(zip->wbuff)); + if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF) + continue; } - } while (zip->stream.avail_in); + if (zip->stream.avail_in == 0) + break; + } if (run == ARCHIVE_Z_FINISH) { uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out; - if (write_to_temp(a, zip->wbuff, bytes) != ARCHIVE_OK) + if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK) return (ARCHIVE_FATAL); if ((zip->crc32flg & ENCODED_CRC32) && bytes) zip->encoded_crc32 = crc32(zip->encoded_crc32, - zip->wbuff, bytes); + zip->wbuff, (unsigned)bytes); } return (s); @@ -596,13 +607,13 @@ _7z_write_data(struct archive_write *a, const void *buff, size_t s) zip = (struct _7zip *)a->format_data; if (s > zip->entry_bytes_remaining) - s = zip->entry_bytes_remaining; + s = (size_t)zip->entry_bytes_remaining; if (s == 0 || zip->cur_file == NULL) return (0); bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN); if (bytes < 0) return (bytes); - zip->entry_crc32 = crc32(zip->entry_crc32, buff, bytes); + zip->entry_crc32 = crc32(zip->entry_crc32, buff, (unsigned)bytes); zip->entry_bytes_remaining -= bytes; return (bytes); } @@ -619,12 +630,12 @@ _7z_finish_entry(struct archive_write *a) return (ARCHIVE_OK); while (zip->entry_bytes_remaining > 0) { - s = zip->entry_bytes_remaining; + s = (size_t)zip->entry_bytes_remaining; if (s > a->null_length) s = a->null_length; r = _7z_write_data(a, a->nulls, s); if (r < 0) - return (r); + return ((int)r); } zip->total_bytes_compressed += zip->stream.total_in; zip->total_bytes_uncompressed += zip->stream.total_out; @@ -727,8 +738,10 @@ _7z_close(struct archive_write *a) zip->total_number_entry - zip->total_number_empty_entry; /* Connect an empty file list. */ - *zip->file_list.last = zip->empty_list.first; - zip->file_list.last = zip->empty_list.last; + if (zip->empty_list.first != NULL) { + *zip->file_list.last = zip->empty_list.first; + zip->file_list.last = zip->empty_list.last; + } /* Connect a directory file list. */ ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) { file_register(zip, (struct file *)n); @@ -844,7 +857,7 @@ enc_uint64(struct archive_write *a, uint64_t val) int i; numdata[0] = 0; - for (i = 1; i < sizeof(numdata); i++) { + for (i = 1; i < (int)sizeof(numdata); i++) { if (val < mask) { numdata[0] |= (uint8_t)val; break; @@ -854,7 +867,7 @@ enc_uint64(struct archive_write *a, uint64_t val) numdata[0] |= mask; mask >>= 1; } - return (compress_out(a, numdata, i, ARCHIVE_Z_RUN)); + return ((int)compress_out(a, numdata, i, ARCHIVE_Z_RUN)); } static int @@ -919,7 +932,7 @@ make_substreamsInfo(struct archive_write *a, struct coder *coders) if (file->size == 0) break; archive_le32enc(crc, file->crc32); - r = compress_out(a, crc, 4, ARCHIVE_Z_RUN); + r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN); if (r < 0) return (r); } @@ -943,7 +956,7 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size, int i, r; if (coders->codec == _7Z_COPY) - numFolders = zip->total_number_nonempty_entry; + numFolders = (int)zip->total_number_nonempty_entry; else numFolders = 1; @@ -1039,7 +1052,7 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size, /* Write Codec ID. */ codec_size &= 0x0f; - r = compress_out(a, &codec_buff[8-codec_size], + r = (int)compress_out(a, &codec_buff[8-codec_size], codec_size, ARCHIVE_Z_RUN); if (r < 0) return (r); @@ -1051,7 +1064,7 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size, return (r); /* Write Codec properties. */ - r = compress_out(a, coders[i].props, + r = (int)compress_out(a, coders[i].props, coders[i].prop_size, ARCHIVE_Z_RUN); if (r < 0) return (r); @@ -1097,7 +1110,7 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size, if (r < 0) return (r); archive_le32enc(crc, header_crc); - r = compress_out(a, crc, 4, ARCHIVE_Z_RUN); + r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN); if (r < 0) return (r); } @@ -1128,11 +1141,11 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size, #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) static uint64_t -utcToFiletime(time_t time, long ns) +utcToFiletime(time_t t, long ns) { uint64_t fileTime; - fileTime = time; + fileTime = t; fileTime *= 10000000; fileTime += ns / 100; fileTime += EPOC_TIME; @@ -1146,7 +1159,7 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti) struct _7zip *zip = (struct _7zip *)a->format_data; struct file *file; int r; - uint8_t mask, byte; + uint8_t b, mask; /* * Make Time Bools. @@ -1183,23 +1196,23 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti) if (r < 0) return (r); - byte = 0; + b = 0; mask = 0x80; file = zip->file_list.first; for (;file != NULL; file = file->next) { if (file->flg & flg) - byte |= mask; + b |= mask; mask >>= 1; if (mask == 0) { - r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); if (r < 0) return (r); mask = 0x80; - byte = 0; + b = 0; } } if (mask != 0x80) { - r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); if (r < 0) return (r); } @@ -1220,7 +1233,7 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti) continue; archive_le64enc(filetime, utcToFiletime(file->times[ti].time, file->times[ti].time_ns)); - r = compress_out(a, filetime, 8, ARCHIVE_Z_RUN); + r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN); if (r < 0) return (r); } @@ -1235,7 +1248,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, struct _7zip *zip = (struct _7zip *)a->format_data; struct file *file; int r; - uint8_t mask, byte; + uint8_t b, mask; /* * Make FilesInfo. @@ -1283,23 +1296,23 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, if (r < 0) return (r); - byte = 0; + b = 0; mask = 0x80; file = zip->file_list.first; for (;file != NULL; file = file->next) { if (file->size == 0) - byte |= mask; + b |= mask; mask >>= 1; if (mask == 0) { - r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); if (r < 0) return (r); mask = 0x80; - byte = 0; + b = 0; } } if (mask != 0x80) { - r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); if (r < 0) return (r); } @@ -1316,25 +1329,25 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, if (r < 0) return (r); - byte = 0; + b = 0; mask = 0x80; file = zip->file_list.first; for (;file != NULL; file = file->next) { if (file->size) continue; if (!file->dir) - byte |= mask; + b |= mask; mask >>= 1; if (mask == 0) { - r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); if (r < 0) return (r); mask = 0x80; - byte = 0; + b = 0; } } if (mask != 0x80) { - r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); if (r < 0) return (r); } @@ -1357,7 +1370,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, file = zip->file_list.first; for (;file != NULL; file = file->next) { - r = compress_out(a, file->utf16name, file->name_len+2, + r = (int)compress_out(a, file->utf16name, file->name_len+2, ARCHIVE_Z_RUN); if (r < 0) return (r); @@ -1413,7 +1426,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, attr |= 1;/* Read Only. */ attr |= ((uint32_t)file->mode) << 16; archive_le32enc(&encattr, attr); - r = compress_out(a, &encattr, 4, ARCHIVE_Z_RUN); + r = (int)compress_out(a, &encattr, 4, ARCHIVE_Z_RUN); if (r < 0) return (r); } @@ -1449,8 +1462,8 @@ static int file_cmp_node(const struct archive_rb_node *n1, const struct archive_rb_node *n2) { - struct file *f1 = (struct file *)n1; - struct file *f2 = (struct file *)n2; + const struct file *f1 = (const struct file *)n1; + const struct file *f2 = (const struct file *)n2; if (f1->name_len == f2->name_len) return (memcmp(f1->utf16name, f2->utf16name, f1->name_len)); @@ -1460,7 +1473,7 @@ file_cmp_node(const struct archive_rb_node *n1, static int file_cmp_key(const struct archive_rb_node *n, const void *key) { - struct file *f = (struct file *)n; + const struct file *f = (const struct file *)n; return (f->name_len - *(const char *)key); } @@ -1487,6 +1500,7 @@ file_new(struct archive_write *a, struct archive_entry *entry, if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) { if (errno == ENOMEM) { + free(file); archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for UTF-16LE"); return (ARCHIVE_FATAL); @@ -1498,6 +1512,7 @@ file_new(struct archive_write *a, struct archive_entry *entry, } file->utf16name = malloc(u16len + 2); if (file->utf16name == NULL) { + free(file); archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Name"); return (ARCHIVE_FATAL); @@ -1505,7 +1520,7 @@ file_new(struct archive_write *a, struct archive_entry *entry, memcpy(file->utf16name, u16, u16len); file->utf16name[u16len+0] = 0; file->utf16name[u16len+1] = 0; - file->name_len = u16len; + file->name_len = (unsigned)u16len; file->mode = archive_entry_mode(entry); if (archive_entry_filetype(entry) == AE_IFREG) file->size = archive_entry_size(entry); @@ -1585,7 +1600,8 @@ file_init_register_empty(struct _7zip *zip) zip->empty_list.last = &(zip->empty_list.first); } -#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) +#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\ + !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) static int compression_unsupported_encoder(struct archive *a, struct la_zstream *lastrm, const char *name) @@ -1669,11 +1685,11 @@ compression_init_encoder_deflate(struct archive *a, * of ugly hackery to convert a const * pointer to * a non-const pointer. */ strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; - strm->avail_in = lastrm->avail_in; - strm->total_in = lastrm->total_in; + strm->avail_in = (uInt)lastrm->avail_in; + strm->total_in = (uLong)lastrm->total_in; strm->next_out = lastrm->next_out; - strm->avail_out = lastrm->avail_out; - strm->total_out = lastrm->total_out; + strm->avail_out = (uInt)lastrm->avail_out; + strm->total_out = (uLong)lastrm->total_out; if (deflateInit2(strm, level, Z_DEFLATED, (withheader)?15:-15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { @@ -1702,11 +1718,11 @@ compression_code_deflate(struct archive *a, * of ugly hackery to convert a const * pointer to * a non-const pointer. */ strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; - strm->avail_in = lastrm->avail_in; - strm->total_in = lastrm->total_in; + strm->avail_in = (uInt)lastrm->avail_in; + strm->total_in = (uLong)lastrm->total_in; strm->next_out = lastrm->next_out; - strm->avail_out = lastrm->avail_out; - strm->total_out = lastrm->total_out; + strm->avail_out = (uInt)lastrm->avail_out; + strm->total_out = (uLong)lastrm->total_out; r = deflate(strm, (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH); lastrm->next_in = strm->next_in; @@ -1908,6 +1924,7 @@ compression_init_encoder_lzma(struct archive *a, if (level > 6) level = 6; if (lzma_lzma_preset(&lzma_opt, level)) { + free(strm); lastrm->real_stream = NULL; archive_set_error(a, ENOMEM, "Internal error initializing compression library"); @@ -2177,6 +2194,8 @@ compression_code_ppmd(struct archive *a, { struct ppmd_stream *strm; + (void)a; /* UNUSED */ + strm = (struct ppmd_stream *)lastrm->real_stream; /* Copy encoded data if there are remaining bytes from previous call. */ @@ -2217,6 +2236,8 @@ compression_end_ppmd(struct archive *a, struct la_zstream *lastrm) { struct ppmd_stream *strm; + (void)a; /* UNUSED */ + strm = (struct ppmd_stream *)lastrm->real_stream; __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context, &g_szalloc); free(strm->buff); diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c index 956b93228..9f17564c3 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c @@ -165,7 +165,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry) * Reject files with empty name. */ pathname = archive_entry_pathname(entry); - if (*pathname == '\0') { + if (pathname == NULL || *pathname == '\0') { archive_set_error(&a->archive, EINVAL, "Invalid filename"); return (ARCHIVE_WARN); @@ -366,7 +366,7 @@ archive_write_ar_data(struct archive_write *a, const void *buff, size_t s) ar = (struct ar_w *)a->format_data; if (s > ar->entry_bytes_remaining) - s = ar->entry_bytes_remaining; + s = (size_t)ar->entry_bytes_remaining; if (ar->is_strtab > 0) { if (ar->has_strtab > 0) { diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c index 9671f60f8..af3105e48 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c @@ -56,8 +56,10 @@ struct { const char *name; int (*setter)(struct archive *); } names[] = { "iso", archive_write_set_format_iso9660 }, { "iso9660", archive_write_set_format_iso9660 }, { "mtree", archive_write_set_format_mtree }, + { "mtree-classic", archive_write_set_format_mtree_classic }, { "newc", archive_write_set_format_cpio_newc }, { "odc", archive_write_set_format_cpio }, + { "oldtar", archive_write_set_format_v7tar }, { "pax", archive_write_set_format_pax }, { "paxr", archive_write_set_format_pax_restricted }, { "posix", archive_write_set_format_pax }, @@ -65,6 +67,8 @@ struct { const char *name; int (*setter)(struct archive *); } names[] = { "shar", archive_write_set_format_shar }, { "shardump", archive_write_set_format_shar_dump }, { "ustar", archive_write_set_format_ustar }, + { "v7tar", archive_write_set_format_v7tar }, + { "v7", archive_write_set_format_v7tar }, { "xar", archive_write_set_format_xar }, { "zip", archive_write_set_format_zip }, { NULL, NULL } diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c index 92b9bfb0b..352649365 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -147,11 +148,13 @@ archive_write_cpio_options(struct archive_write *a, const char *key, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: unknown keyword ``%s''", a->format_name, key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } /* @@ -186,7 +189,7 @@ synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry) /* Don't store a mapping if we don't need to. */ if (archive_entry_nlink(entry) < 2) { - return ++cpio->ino_next; + return (int)(++cpio->ino_next); } /* Look up old ino; if we have it, this is a hardlink @@ -197,7 +200,7 @@ synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry) } /* Assign a new index number. */ - ino_new = ++cpio->ino_next; + ino_new = (int)(++cpio->ino_next); /* Ensure space for the new mapping. */ if (cpio->ino_list_size <= cpio->ino_list_next) { @@ -278,18 +281,37 @@ write_header(struct archive_write *a, struct archive_entry *entry) int64_t ino; char h[76]; struct archive_string_conv *sconv; + struct archive_entry *entry_main; size_t len; cpio = (struct cpio *)a->format_data; ret_final = ARCHIVE_OK; sconv = get_sconv(a); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif + ret = archive_entry_pathname_l(entry, &path, &len, sconv); if (ret != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathname"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate pathname '%s' to %s", @@ -308,11 +330,13 @@ write_header(struct archive_write *a, struct archive_entry *entry) if (ino < 0) { archive_set_error(&a->archive, ENOMEM, "No memory for ino translation table"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } else if (ino > 0777777) { archive_set_error(&a->archive, ERANGE, "Too many files for this cpio format"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } format_octal(ino & 0777777, h + c_ino_offset, c_ino_size); @@ -339,7 +363,8 @@ write_header(struct archive_write *a, struct archive_entry *entry) if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Linkname"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate linkname '%s' to %s", @@ -356,25 +381,35 @@ write_header(struct archive_write *a, struct archive_entry *entry) if (ret) { archive_set_error(&a->archive, ERANGE, "File is too large for cpio format."); - return (ARCHIVE_FAILED); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; } ret = __archive_write_output(a, h, sizeof(h)); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } ret = __archive_write_output(a, path, pathlength); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } cpio->entry_bytes_remaining = archive_entry_size(entry); /* Write the symlink now. */ if (p != NULL && *p != '\0') { ret = __archive_write_output(a, p, strlen(p)); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } } +exit_write_header: + if (entry_main) + archive_entry_free(entry_main); return (ret_final); } @@ -386,7 +421,7 @@ archive_write_cpio_data(struct archive_write *a, const void *buff, size_t s) cpio = (struct cpio *)a->format_data; if (s > cpio->entry_bytes_remaining) - s = cpio->entry_bytes_remaining; + s = (size_t)cpio->entry_bytes_remaining; ret = __archive_write_output(a, buff, s); cpio->entry_bytes_remaining -= s; @@ -422,7 +457,7 @@ format_octal_recursive(int64_t v, char *p, int s) if (s == 0) return (v); v = format_octal_recursive(v, p+1, s-1); - *p = '0' + (v & 7); + *p = '0' + ((char)v & 7); return (v >> 3); } @@ -460,5 +495,6 @@ archive_write_cpio_finish_entry(struct archive_write *a) struct cpio *cpio; cpio = (struct cpio *)a->format_data; - return (__archive_write_nulls(a, cpio->entry_bytes_remaining)); + return (__archive_write_nulls(a, + (size_t)cpio->entry_bytes_remaining)); } diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c index d06c391a8..a9bfa808c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2006 Rudolf Marek SYSGO s.r.o. + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -154,11 +155,13 @@ archive_write_newc_options(struct archive_write *a, const char *key, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: unknown keyword ``%s''", a->format_name, key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static struct archive_string_conv * @@ -220,6 +223,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) int pathlength, ret, ret_final; char h[c_header_size]; struct archive_string_conv *sconv; + struct archive_entry *entry_main; size_t len; int pad; @@ -227,12 +231,30 @@ write_header(struct archive_write *a, struct archive_entry *entry) ret_final = ARCHIVE_OK; sconv = get_sconv(a); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif + ret = archive_entry_pathname_l(entry, &path, &len, sconv); if (ret != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathname"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate pathname '%s' to %s", @@ -284,7 +306,8 @@ write_header(struct archive_write *a, struct archive_entry *entry) if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Likname"); - return (ARCHIVE_FATAL); + ret_final = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate linkname '%s' to %s", @@ -301,37 +324,51 @@ write_header(struct archive_write *a, struct archive_entry *entry) if (ret) { archive_set_error(&a->archive, ERANGE, "File is too large for this format."); - return (ARCHIVE_FAILED); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; } ret = __archive_write_output(a, h, c_header_size); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } /* Pad pathname to even length. */ ret = __archive_write_output(a, path, pathlength); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } pad = PAD4(pathlength + c_header_size); if (pad) { ret = __archive_write_output(a, "\0\0\0", pad); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } } cpio->entry_bytes_remaining = archive_entry_size(entry); - cpio->padding = PAD4(cpio->entry_bytes_remaining); + cpio->padding = (int)PAD4(cpio->entry_bytes_remaining); /* Write the symlink now. */ if (p != NULL && *p != '\0') { ret = __archive_write_output(a, p, strlen(p)); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } pad = PAD4(strlen(p)); ret = __archive_write_output(a, "\0\0\0", pad); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) { + ret_final = ARCHIVE_FATAL; + goto exit_write_header; + } } +exit_write_header: + if (entry_main) + archive_entry_free(entry_main); return (ret_final); } @@ -343,7 +380,7 @@ archive_write_newc_data(struct archive_write *a, const void *buff, size_t s) cpio = (struct cpio *)a->format_data; if (s > cpio->entry_bytes_remaining) - s = cpio->entry_bytes_remaining; + s = (size_t)cpio->entry_bytes_remaining; ret = __archive_write_output(a, buff, s); cpio->entry_bytes_remaining -= s; @@ -416,5 +453,6 @@ archive_write_newc_finish_entry(struct archive_write *a) struct cpio *cpio; cpio = (struct cpio *)a->format_data; - return (__archive_write_nulls(a, cpio->entry_bytes_remaining + cpio->padding)); + return (__archive_write_nulls(a, + (size_t)cpio->entry_bytes_remaining + cpio->padding)); } diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c index e091ed23f..13942c132 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). * Author: Jonas Gastal <jgastal@profusion.mobi> - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * * All rights reserved. * @@ -177,7 +177,8 @@ archive_write_set_format_gnutar(struct archive *_a) gnutar = (struct gnutar *)calloc(1, sizeof(*gnutar)); if (gnutar == NULL) { - archive_set_error(&a->archive, ENOMEM, "Can't allocate gnutar data"); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate gnutar data"); return (ARCHIVE_FATAL); } a->format_data = gnutar; @@ -213,11 +214,13 @@ archive_write_gnutar_options(struct archive_write *a, const char *key, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: unknown keyword ``%s''", a->format_name, key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -244,8 +247,8 @@ archive_write_gnutar_finish_entry(struct archive_write *a) int ret; gnutar = (struct gnutar *)a->format_data; - ret = __archive_write_nulls(a, - gnutar->entry_bytes_remaining + gnutar->entry_padding); + ret = __archive_write_nulls(a, (size_t) + (gnutar->entry_bytes_remaining + gnutar->entry_padding)); gnutar->entry_bytes_remaining = gnutar->entry_padding = 0; return (ret); } @@ -258,7 +261,7 @@ archive_write_gnutar_data(struct archive_write *a, const void *buff, size_t s) gnutar = (struct gnutar *)a->format_data; if (s > gnutar->entry_bytes_remaining) - s = gnutar->entry_bytes_remaining; + s = (size_t)gnutar->entry_bytes_remaining; ret = __archive_write_output(a, buff, s); gnutar->entry_bytes_remaining -= s; if (ret != ARCHIVE_OK) @@ -275,6 +278,7 @@ archive_write_gnutar_header(struct archive_write *a, int tartype; struct gnutar *gnutar; struct archive_string_conv *sconv; + struct archive_entry *entry_main; gnutar = (struct gnutar *)a->format_data; @@ -298,33 +302,95 @@ archive_write_gnutar_header(struct archive_write *a, if (AE_IFDIR == archive_entry_filetype(entry)) { const char *p; - char *t; + size_t path_length; /* * Ensure a trailing '/'. Modify the entry so * the client sees the change. */ - p = archive_entry_pathname(entry); - if (p[strlen(p) - 1] != '/') { - t = (char *)malloc(strlen(p) + 2); - if (t == NULL) { +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + archive_wstring_free(&ws); + return(ARCHIVE_FATAL); + } + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w(entry, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { archive_set_error(&a->archive, ENOMEM, - "Can't allocate gnutar data"); + "Can't allocate ustar data"); + archive_string_free(&as); return(ARCHIVE_FATAL); } - strcpy(t, p); - strcat(t, "/"); - archive_entry_copy_pathname(entry, t); - free(t); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname(entry, as.s); + archive_string_free(&as); } } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif r = archive_entry_pathname_l(entry, &(gnutar->pathname), &(gnutar->pathname_length), sconv); if (r != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathame"); - return (ARCHIVE_FATAL); + ret = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate pathname '%s' to %s", @@ -338,7 +404,8 @@ archive_write_gnutar_header(struct archive_write *a, if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Uname"); - return (ARCHIVE_FATAL); + ret = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -353,7 +420,8 @@ archive_write_gnutar_header(struct archive_write *a, if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Gname"); - return (ARCHIVE_FATAL); + ret = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -370,7 +438,8 @@ archive_write_gnutar_header(struct archive_write *a, if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Linkname"); - return (ARCHIVE_FATAL); + ret = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -386,7 +455,8 @@ archive_write_gnutar_header(struct archive_write *a, if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Linkname"); - return (ARCHIVE_FATAL); + ret = ARCHIVE_FATAL; + goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -400,7 +470,7 @@ archive_write_gnutar_header(struct archive_write *a, size_t todo = gnutar->linkname_length; struct archive_entry *temp = archive_entry_new2(&a->archive); - /* Uname/gname here don't really matter since noone reads them; + /* Uname/gname here don't really matter since no one reads them; * these are the values that GNU tar happens to use on FreeBSD. */ archive_entry_set_uname(temp, "root"); archive_entry_set_gname(temp, "wheel"); @@ -409,18 +479,18 @@ archive_write_gnutar_header(struct archive_write *a, archive_entry_set_size(temp, gnutar->linkname_length + 1); ret = archive_format_gnutar_header(a, buff, temp, 'K'); if (ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; ret = __archive_write_output(a, buff, 512); if(ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; archive_entry_free(temp); /* Write as many 512 bytes blocks as needed to write full name. */ ret = __archive_write_output(a, gnutar->linkname, todo); if(ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)todo)); if (ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; } /* If pathname is longer than 100 chars we need to add an 'L' header. */ @@ -429,7 +499,7 @@ archive_write_gnutar_header(struct archive_write *a, size_t todo = gnutar->pathname_length; struct archive_entry *temp = archive_entry_new2(&a->archive); - /* Uname/gname here don't really matter since noone reads them; + /* Uname/gname here don't really matter since no one reads them; * these are the values that GNU tar happens to use on FreeBSD. */ archive_entry_set_uname(temp, "root"); archive_entry_set_gname(temp, "wheel"); @@ -438,18 +508,18 @@ archive_write_gnutar_header(struct archive_write *a, archive_entry_set_size(temp, gnutar->pathname_length + 1); ret = archive_format_gnutar_header(a, buff, temp, 'L'); if (ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; ret = __archive_write_output(a, buff, 512); if(ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; archive_entry_free(temp); /* Write as many 512 bytes blocks as needed to write full name. */ ret = __archive_write_output(a, pathname, todo); if(ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)todo)); if (ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; } if (archive_entry_hardlink(entry) != NULL) { @@ -466,28 +536,35 @@ archive_write_gnutar_header(struct archive_write *a, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "tar format cannot archive socket"); - return (ARCHIVE_FAILED); + ret = ARCHIVE_FAILED; + goto exit_write_header; default: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "tar format cannot archive this (mode=0%lo)", (unsigned long)archive_entry_mode(entry)); - return (ARCHIVE_FAILED); + ret = ARCHIVE_FAILED; + goto exit_write_header; } ret = archive_format_gnutar_header(a, buff, entry, tartype); if (ret < ARCHIVE_WARN) - return (ret); + goto exit_write_header; if (ret2 < ret) ret = ret2; ret2 = __archive_write_output(a, buff, 512); - if (ret2 < ARCHIVE_WARN) - return (ret2); + if (ret2 < ARCHIVE_WARN) { + ret = ret2; + goto exit_write_header; + } if (ret2 < ret) ret = ret2; gnutar->entry_bytes_remaining = archive_entry_size(entry); gnutar->entry_padding = 0x1ff & (-(int64_t)gnutar->entry_bytes_remaining); +exit_write_header: + if (entry_main) + archive_entry_free(entry_main); return (ret); } diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c index 0b9aaf941..e7226256b 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -994,7 +994,7 @@ static void isoent_remove_child(struct isoent *, struct isoent *); static void isoent_setup_directory_location(struct iso9660 *, int, struct vdd *); static void isoent_setup_file_location(struct iso9660 *, int); -static int get_path_component(char *, int, const char *); +static int get_path_component(char *, size_t, const char *); static int isoent_tree(struct archive_write *, struct isoent **); static struct isoent *isoent_find_child(struct isoent *, const char *); static struct isoent *isoent_find_entry(struct isoent *, const char *); @@ -1507,6 +1507,11 @@ iso9660_options(struct archive_write *a, const char *key, const char *value) break; } + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); + invalid_value: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid value for option ``%s''", key); @@ -1693,7 +1698,7 @@ wb_write_padding_to_temp(struct archive_write *a, int64_t csize) size_t ns; int ret; - ns = csize % LOGICAL_BLOCK_SIZE; + ns = (size_t)(csize % LOGICAL_BLOCK_SIZE); if (ns != 0) ret = write_null(a, LOGICAL_BLOCK_SIZE - ns); else @@ -1720,8 +1725,8 @@ write_iso9660_data(struct archive_write *a, const void *buff, size_t s) struct content *con; size_t ts; - ts = MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE - - iso9660->cur_file->cur_content->size; + ts = (size_t)(MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE - + iso9660->cur_file->cur_content->size); if (iso9660->zisofs.detect_magic) zisofs_detect_magic(a, buff, ts); @@ -1741,9 +1746,9 @@ write_iso9660_data(struct archive_write *a, const void *buff, size_t s) return (ARCHIVE_FATAL); /* Compute the logical block number. */ - iso9660->cur_file->cur_content->blocks = - (iso9660->cur_file->cur_content->size - + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS; + iso9660->cur_file->cur_content->blocks = (int) + ((iso9660->cur_file->cur_content->size + + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS); /* * Make next extent. @@ -1791,7 +1796,7 @@ iso9660_write_data(struct archive_write *a, const void *buff, size_t s) if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG) return (0); if (s > iso9660->bytes_remaining) - s = iso9660->bytes_remaining; + s = (size_t)iso9660->bytes_remaining; if (s == 0) return (0); @@ -1833,9 +1838,9 @@ iso9660_finish_entry(struct archive_write *a) return (ARCHIVE_FATAL); /* Compute the logical block number. */ - iso9660->cur_file->cur_content->blocks = - (iso9660->cur_file->cur_content->size - + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS; + iso9660->cur_file->cur_content->blocks = (int) + ((iso9660->cur_file->cur_content->size + + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS); /* Add the current file to data file list. */ isofile_add_data_file(iso9660, iso9660->cur_file); @@ -1852,7 +1857,7 @@ iso9660_close(struct archive_write *a) iso9660 = a->format_data; /* - * Write remaining data out to the temprary file. + * Write remaining data out to the temporary file. */ if (wb_remaining(a) > 0) { ret = wb_write_out(a); @@ -1881,7 +1886,7 @@ iso9660_close(struct archive_write *a) ret = zisofs_rewind_boot_file(a); if (ret < 0) return (ret); - /* Write remaining data out to the temprary file. */ + /* Write remaining data out to the temporary file. */ if (wb_remaining(a) > 0) { ret = wb_write_out(a); if (ret < 0) @@ -2239,7 +2244,7 @@ set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s, onepad = 0; if (vdc == VDC_UCS2) { struct iso9660 *iso9660 = a->format_data; - if (archive_strncpy_in_locale(&iso9660->utf16be, s, strlen(s), + if (archive_strncpy_l(&iso9660->utf16be, s, strlen(s), iso9660->sconv_to_utf16be) != 0 && errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for UTF-16BE"); @@ -2542,7 +2547,7 @@ set_date_time(unsigned char *p, time_t t) set_digit(p+10, 2, tm.tm_min); set_digit(p+12, 2, tm.tm_sec); set_digit(p+14, 2, 0); - set_num_712(p+16, get_gmoffset(&tm)/(60*15)); + set_num_712(p+16, (char)(get_gmoffset(&tm)/(60*15))); } static void @@ -2564,7 +2569,7 @@ set_time_915(unsigned char *p, time_t t) set_num_711(p+3, tm.tm_hour); set_num_711(p+4, tm.tm_min); set_num_711(p+5, tm.tm_sec); - set_num_712(p+6, get_gmoffset(&tm)/(60*15)); + set_num_712(p+6, (char)(get_gmoffset(&tm)/(60*15))); } @@ -2884,7 +2889,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len, if (nmmax > 0xff) nmmax = 0xff; while (nmlen + 5 > nmmax) { - length = nmmax; + length = (int)nmmax; if (bp != NULL) { bp[3] = length; bp[5] = 0x01;/* Alternate Name continues @@ -2907,7 +2912,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len, bp[4] = 1; /* version */ } } - length = 5 + nmlen; + length = 5 + (int)nmlen; if (bp != NULL) { bp[3] = length; bp[5] = 0; @@ -2936,8 +2941,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len, bp = extra_next_record(&ctl, length); if (bp != NULL) { mode_t mode; - uid_t uid; - gid_t gid; + int64_t uid; + int64_t gid; mode = archive_entry_mode(file->entry); uid = archive_entry_uid(file->entry); @@ -2970,8 +2975,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len, /* file links (stat.st_nlink) */ set_num_733(bp+13, archive_entry_nlink(file->entry)); - set_num_733(bp+21, uid); - set_num_733(bp+29, gid); + set_num_733(bp+21, (uint32_t)uid); + set_num_733(bp+29, (uint32_t)gid); /* File Serial Number */ if (pxent->dir) set_num_733(bp+37, pxent->dir_location); @@ -3352,8 +3357,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len, bp[3] = length; bp[4] = 1; /* version */ dev = (uint64_t)archive_entry_rdev(file->entry); - set_num_733(bp + 5, dev >> 32); - set_num_733(bp + 13, dev & 0xFFFFFFFF); + set_num_733(bp + 5, (uint32_t)(dev >> 32)); + set_num_733(bp + 13, (uint32_t)(dev & 0xFFFFFFFF)); bp += length; } extra_tell_used_size(&ctl, length); @@ -3487,7 +3492,7 @@ set_directory_record(unsigned char *p, size_t n, struct isoent *isoent, set_num_733(bp+11, xisoent->dir_block * LOGICAL_BLOCK_SIZE); else - set_num_733(bp+11, file->cur_content->size); + set_num_733(bp+11, (uint32_t)file->cur_content->size); /* Recording Date and Time */ /* NOTE: * If a file type is symbolic link, you are seeing this @@ -3506,7 +3511,7 @@ set_directory_record(unsigned char *p, size_t n, struct isoent *isoent, /* Volume Sequence Number */ set_num_723(bp+29, iso9660->volume_sequence_number); /* Length of File Identifier */ - set_num_711(bp+33, fi_len); + set_num_711(bp+33, (unsigned char)fi_len); /* File Identifier */ switch (t) { case DIR_REC_VD: @@ -3537,20 +3542,20 @@ set_directory_record(unsigned char *p, size_t n, struct isoent *isoent, if (t == DIR_REC_VD) { if (p != NULL) /* Length of Directory Record */ - set_num_711(p, dr_len); + set_num_711(p, (unsigned char)dr_len); else - isoent->dr_len.vd = dr_len; - return (dr_len); + isoent->dr_len.vd = (int)dr_len; + return ((int)dr_len); } /* Rockridge */ if (iso9660->opt.rr && vdd_type != VDD_JOLIET) - dr_len = set_directory_record_rr(bp, dr_len, + dr_len = set_directory_record_rr(bp, (int)dr_len, isoent, iso9660, t); if (p != NULL) /* Length of Directory Record */ - set_num_711(p, dr_len); + set_num_711(p, (unsigned char)dr_len); else { /* * Save the size which is needed to write this @@ -3563,15 +3568,15 @@ set_directory_record(unsigned char *p, size_t n, struct isoent *isoent, * in switch .... */ break; case DIR_REC_SELF: - isoent->dr_len.self = dr_len; break; + isoent->dr_len.self = (int)dr_len; break; case DIR_REC_PARENT: - isoent->dr_len.parent = dr_len; break; + isoent->dr_len.parent = (int)dr_len; break; case DIR_REC_NORMAL: - isoent->dr_len.normal = dr_len; break; + isoent->dr_len.normal = (int)dr_len; break; } } - return (dr_len); + return ((int)dr_len); } /* @@ -3664,7 +3669,7 @@ wb_set_offset(struct archive_write *a, int64_t off) iso9660->wbuff_tail = iso9660->wbuff_offset + used; if (iso9660->wbuff_offset < iso9660->wbuff_written) { if (used > 0 && - write_to_temp(a, iso9660->wbuff, used) != ARCHIVE_OK) + write_to_temp(a, iso9660->wbuff, (size_t)used) != ARCHIVE_OK) return (ARCHIVE_FATAL); iso9660->wbuff_offset = iso9660->wbuff_written; lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET); @@ -3683,13 +3688,13 @@ wb_set_offset(struct archive_write *a, int64_t off) iso9660->wbuff_offset = off; iso9660->wbuff_remaining = sizeof(iso9660->wbuff); } else if (off <= iso9660->wbuff_tail) { - iso9660->wbuff_remaining = - sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset); + iso9660->wbuff_remaining = (size_t) + (sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset)); } else { ext_bytes = off - iso9660->wbuff_tail; - iso9660->wbuff_remaining = sizeof(iso9660->wbuff) - - (iso9660->wbuff_tail - iso9660->wbuff_offset); - while (ext_bytes >= iso9660->wbuff_remaining) { + iso9660->wbuff_remaining = (size_t)(sizeof(iso9660->wbuff) + - (iso9660->wbuff_tail - iso9660->wbuff_offset)); + while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) { if (write_null(a, (size_t)iso9660->wbuff_remaining) != ARCHIVE_OK) return (ARCHIVE_FATAL); @@ -4250,7 +4255,7 @@ _write_path_table(struct archive_write *a, int type_m, int depth, bp = wb -1; } /* Length of Directory Identifier */ - set_num_711(bp+1, len); + set_num_711(bp+1, (unsigned char)len); /* Extended Attribute Record Length */ set_num_711(bp+2, 0); /* Location of Extent */ @@ -4273,7 +4278,7 @@ _write_path_table(struct archive_write *a, int type_m, int depth, bp[9+len] = 0; len++; } - wsize += 8 + len; + wsize += 8 + (int)len; bp += 8 + len; } if ((bp + 1) > wb) { @@ -4508,8 +4513,7 @@ write_file_descriptors(struct archive_write *a) /* Write the boot file contents. */ if (iso9660->el_torito.boot != NULL) { - struct isofile *file = iso9660->el_torito.boot->file; - + file = iso9660->el_torito.boot->file; blocks = file->content.blocks; offset = file->content.offset_of_temp; if (offset != 0) { @@ -4810,13 +4814,19 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file) struct archive_wstring ws; if (wp != NULL) { + int r; archive_string_init(&ws); archive_wstrcpy(&ws, wp); cleanup_backslash_2(ws.s); archive_string_empty(&(file->parentdir)); - archive_string_append_from_wcs(&(file->parentdir), + r = archive_string_append_from_wcs(&(file->parentdir), ws.s, ws.length); archive_wstring_free(&ws); + if (r < 0 && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } } } #endif @@ -4919,14 +4929,20 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file) struct archive_wstring ws; if (wp != NULL) { + int r; archive_string_init(&ws); archive_wstrcpy(&ws, wp); cleanup_backslash_2(ws.s); archive_string_empty(&(file->symlink)); - archive_string_append_from_wcs( + r = archive_string_append_from_wcs( &(file->symlink), ws.s, ws.length); archive_wstring_free(&ws); + if (r < 0 && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } } } #endif @@ -5422,8 +5438,8 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location) iso9660->total_file_block = 0; if ((isoent = iso9660->el_torito.catalog) != NULL) { isoent->file->content.location = location; - block = (archive_entry_size(isoent->file->entry) + - LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS; + block = (int)((archive_entry_size(isoent->file->entry) + + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS); location += block; iso9660->total_file_block += block; } @@ -5431,8 +5447,9 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location) isoent->file->content.location = location; size = fd_boot_image_size(iso9660->el_torito.media_type); if (size == 0) - size = archive_entry_size(isoent->file->entry); - block = (size + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS; + size = (size_t)archive_entry_size(isoent->file->entry); + block = ((int)size + LOGICAL_BLOCK_SIZE -1) + >> LOGICAL_BLOCK_BITS; location += block; iso9660->total_file_block += block; isoent->file->content.blocks = block; @@ -5493,10 +5510,10 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location) } static int -get_path_component(char *name, int n, const char *fn) +get_path_component(char *name, size_t n, const char *fn) { char *p; - int l; + size_t l; p = strchr(fn, '/'); if (p == NULL) { @@ -5509,7 +5526,7 @@ get_path_component(char *name, int n, const char *fn) memcpy(name, fn, l); name[l] = '\0'; - return (l); + return ((int)l); } /* @@ -5802,17 +5819,18 @@ idr_ensure_poolsize(struct archive_write *a, struct idr *idr, { if (idr->pool_size < cnt) { + void *p; const int bk = (1 << 7) - 1; int psize; psize = (cnt + bk) & ~bk; - idr->idrent_pool = realloc(idr->idrent_pool, - sizeof(struct idrent) * psize); - if (idr->idrent_pool == NULL) { + p = realloc(idr->idrent_pool, sizeof(struct idrent) * psize); + if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); return (ARCHIVE_FATAL); } + idr->idrent_pool = (struct idrent *)p; idr->pool_size = psize; } return (ARCHIVE_OK); @@ -6000,7 +6018,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, char *dot, *xdot; int ext_off, noff, weight; - l = np->file->basename.length; + l = (int)np->file->basename.length; p = malloc(l+31+2+1); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, @@ -6064,7 +6082,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, ext_off = l; } else { *dot = '.'; - ext_off = dot - p; + ext_off = (int)(dot - p); if (iso9660->opt.iso_level == 1) { if (dot - p <= 8) { @@ -6091,11 +6109,11 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, ext_off = dnmax; } } else if (l > ffmax) { - int extlen = strlen(dot); + int extlen = (int)strlen(dot); int xdoff; if (xdot != NULL) - xdoff = xdot - p; + xdoff = (int)(xdot - p); else xdoff = 0; @@ -6132,7 +6150,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, } /* Save an offset of a file name extension to sort files. */ np->ext_off = ext_off; - np->ext_len = strlen(&p[ext_off]); + np->ext_len = (int)strlen(&p[ext_off]); np->id_len = l = ext_off + np->ext_len; /* Make an offset of the number which is used to be set @@ -6249,30 +6267,35 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, p += 2; lt -= 2; } - ext_off = dot - (unsigned char *)np->identifier; + ext_off = (int)(dot - (unsigned char *)np->identifier); np->ext_off = ext_off; - np->ext_len = l - ext_off; - np->id_len = l; + np->ext_len = (int)l - ext_off; + np->id_len = (int)l; /* * Get a length of MBS of a full-pathname. */ if ((int)np->file->basename_utf16.length > ffmax) { - archive_strncpy_in_locale(&iso9660->mbs, + if (archive_strncpy_l(&iso9660->mbs, (const char *)np->identifier, l, - iso9660->sconv_from_utf16be); - np->mb_len = iso9660->mbs.length; + iso9660->sconv_from_utf16be) != 0 && + errno == ENOMEM) { + archive_set_error(&a->archive, errno, + "No memory"); + return (ARCHIVE_FATAL); + } + np->mb_len = (int)iso9660->mbs.length; if (np->mb_len != (int)np->file->basename.length) weight = np->mb_len; } else - np->mb_len = np->file->basename.length; + np->mb_len = (int)np->file->basename.length; /* If a length of full-pathname is longer than 240 bytes, * it violates Joliet extensions regulation. */ if (parent_len + np->mb_len > 240) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "The regulation of Joliet extensions;" - " A lenght of a full-pathname of `%s' is " + " A length of a full-pathname of `%s' is " "longer than 240 bytes, (p=%d, b=%d)", archive_entry_pathname(np->file->entry), (int)parent_len, (int)np->mb_len); @@ -6280,7 +6303,7 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, } /* Make an offset of the number which is used to be set - * hexadecimal number to avoid duplicate identififier. */ + * hexadecimal number to avoid duplicate identifier. */ if ((int)l == ffmax) noff = ext_off - 6; else if ((int)l == ffmax-2) @@ -6300,7 +6323,7 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, } /* - * This comparing rule is acording to ISO9660 Standard 9.3 + * This comparing rule is according to ISO9660 Standard 9.3 */ static int isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2) @@ -6360,7 +6383,7 @@ isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2) if (0x20 != *s2++) return (0x20 - *(const unsigned char *)(s2 - 1)); - } else if (p1->ext_len < p2->ext_len) { + } else if (p1->ext_len > p2->ext_len) { s1 += l; l = p1->ext_len - p2->ext_len; while (l--) @@ -6448,7 +6471,7 @@ isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2) while (l--) if (0 != *s2++) return (- *(const unsigned char *)(s2 - 1)); - } else if (p1->ext_len < p2->ext_len) { + } else if (p1->ext_len > p2->ext_len) { s1 += l; l = p1->ext_len - p2->ext_len; while (l--) @@ -6514,8 +6537,7 @@ isoent_traverse_tree(struct archive_write *a, struct vdd* vdd) struct idr idr; int depth; int r; - int (*genid)(struct archive_write *a, struct isoent *isoent, - struct idr *idr); + int (*genid)(struct archive_write *, struct isoent *, struct idr *); idr_init(iso9660, vdd, &idr); np = vdd->rootent; @@ -6896,12 +6918,22 @@ isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd, switch (vdd->vdd_type) { case VDD_PRIMARY: case VDD_ENHANCED: +#ifdef __COMPAR_FN_T + qsort(enttbl, pt->cnt, sizeof(struct isoent *), + (__compar_fn_t)_compare_path_table); +#else qsort(enttbl, pt->cnt, sizeof(struct isoent *), _compare_path_table); +#endif break; case VDD_JOLIET: +#ifdef __COMPAR_FN_T + qsort(enttbl, pt->cnt, sizeof(struct isoent *), + (__compar_fn_t)_compare_path_table_joliet); +#else qsort(enttbl, pt->cnt, sizeof(struct isoent *), _compare_path_table_joliet); +#endif break; } for (i = 0; i < pt->cnt; i++) @@ -7284,7 +7316,7 @@ setup_boot_information(struct archive_write *a) size_t rsize; ssize_t i, rs; - if (size > sizeof(buff)) + if (size > (int64_t)sizeof(buff)) rsize = sizeof(buff); else rsize = (size_t)size; @@ -7370,7 +7402,7 @@ zisofs_init(struct archive_write *a, struct isofile *file) struct iso9660 *iso9660 = a->format_data; #ifdef HAVE_ZLIB_H uint64_t tsize; - size_t ceil, bpsize; + size_t _ceil, bpsize; int r; #endif @@ -7405,12 +7437,13 @@ zisofs_init(struct archive_write *a, struct isofile *file) /* Mark file->zisofs to create RRIP 'ZF' Use Entry. */ file->zisofs.header_size = ZF_HEADER_SIZE >> 2; file->zisofs.log2_bs = ZF_LOG2_BS; - file->zisofs.uncompressed_size = archive_entry_size(file->entry); + file->zisofs.uncompressed_size = + (uint32_t)archive_entry_size(file->entry); /* Calculate a size of Block Pointers of zisofs. */ - ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1) + _ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1) >> file->zisofs.log2_bs; - iso9660->zisofs.block_pointers_cnt = ceil + 1; + iso9660->zisofs.block_pointers_cnt = (int)_ceil + 1; iso9660->zisofs.block_pointers_idx = 0; /* Ensure a buffer size used for Block Pointers */ @@ -7433,13 +7466,14 @@ zisofs_init(struct archive_write *a, struct isofile *file) * file. */ tsize = ZF_HEADER_SIZE + bpsize; - if (write_null(a, tsize) != ARCHIVE_OK) + if (write_null(a, (size_t)tsize) != ARCHIVE_OK) return (ARCHIVE_FATAL); /* * Initialize some variables to make zisofs. */ - archive_le32enc(&(iso9660->zisofs.block_pointers[0]), tsize); + archive_le32enc(&(iso9660->zisofs.block_pointers[0]), + (uint32_t)tsize); iso9660->zisofs.remaining = file->zisofs.uncompressed_size; iso9660->zisofs.making = 1; iso9660->zisofs.allzero = 1; @@ -7461,14 +7495,14 @@ zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s) uint32_t uncompressed_size; unsigned char header_size; unsigned char log2_bs; - size_t ceil, doff; + size_t _ceil, doff; uint32_t bst, bed; int magic_max; int64_t entry_size; entry_size = archive_entry_size(file->entry); - if (sizeof(iso9660->zisofs.magic_buffer) > entry_size) - magic_max = entry_size; + if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size) + magic_max = (int)entry_size; else magic_max = sizeof(iso9660->zisofs.magic_buffer); @@ -7485,7 +7519,7 @@ zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s) l = s; memcpy(iso9660->zisofs.magic_buffer + iso9660->zisofs.magic_cnt, buff, l); - iso9660->zisofs.magic_cnt += l; + iso9660->zisofs.magic_cnt += (int)l; if (iso9660->zisofs.magic_cnt < magic_max) return; } @@ -7509,16 +7543,16 @@ zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s) return;/* Invalid or not supported header. */ /* Calculate a size of Block Pointers of zisofs. */ - ceil = (uncompressed_size + + _ceil = (uncompressed_size + (ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs; - doff = (ceil + 1) * 4 + 16; - if (entry_size < doff) + doff = (_ceil + 1) * 4 + 16; + if (entry_size < (int64_t)doff) return;/* Invalid data. */ /* Check every Block Pointer has valid value. */ p = magic_buff + 16; endp = magic_buff + magic_max; - while (ceil && p + 8 <= endp) { + while (_ceil && p + 8 <= endp) { bst = archive_le32dec(p); if (bst != doff) return;/* Invalid data. */ @@ -7527,7 +7561,7 @@ zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s) if (bed < bst || bed > entry_size) return;/* Invalid data. */ doff += bed - bst; - ceil--; + _ceil--; } file->zisofs.uncompressed_size = uncompressed_size; @@ -7555,7 +7589,7 @@ zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s) zstrm = &(iso9660->zisofs.stream); zstrm->next_out = wb_buffptr(a); - zstrm->avail_out = wb_remaining(a); + zstrm->avail_out = (uInt)wb_remaining(a); b = (const unsigned char *)buff; do { avail = ZF_BLOCK_SIZE - zstrm->total_in; @@ -7569,7 +7603,7 @@ zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s) flush = Z_FINISH; zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b; - zstrm->avail_in = avail; + zstrm->avail_in = (uInt)avail; /* * Check if current data block are all zero. @@ -7625,7 +7659,7 @@ zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s) iso9660->zisofs.total_size += csize; iso9660->cur_file->cur_content->size += csize; zstrm->next_out = wb_buffptr(a); - zstrm->avail_out = wb_remaining(a); + zstrm->avail_out = (uInt)wb_remaining(a); break; default: archive_set_error(&a->archive, @@ -7644,7 +7678,7 @@ zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s) iso9660->zisofs.block_pointers_idx ++; archive_le32enc(&(iso9660->zisofs.block_pointers[ iso9660->zisofs.block_pointers_idx]), - iso9660->zisofs.total_size); + (uint32_t)iso9660->zisofs.total_size); r = zisofs_init_zstream(a); if (r != ARCHIVE_OK) return (ARCHIVE_FATAL); @@ -7770,13 +7804,13 @@ zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs, const unsigned char *p, size_t bytes) { size_t avail = bytes; - size_t ceil, xsize; + size_t _ceil, xsize; /* Allocate block pointers buffer. */ - ceil = (zisofs->pz_uncompressed_size + + _ceil = (size_t)((zisofs->pz_uncompressed_size + (((int64_t)1) << zisofs->pz_log2_bs) - 1) - >> zisofs->pz_log2_bs; - xsize = (ceil + 1) * 4; + >> zisofs->pz_log2_bs); + xsize = (_ceil + 1) * 4; if (zisofs->block_pointers == NULL) { size_t alloc = ((xsize >> 10) + 1) << 10; zisofs->block_pointers = malloc(alloc); @@ -7789,7 +7823,7 @@ zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs, zisofs->block_pointers_size = xsize; /* Allocate uncompressed data buffer. */ - zisofs->uncompressed_buffer_size = 1UL << zisofs->pz_log2_bs; + zisofs->uncompressed_buffer_size = (size_t)1UL << zisofs->pz_log2_bs; /* * Read the file header, and check the magic code of zisofs. @@ -7859,7 +7893,7 @@ zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs, return (rs); if (!zisofs->initialized) { /* We need more data. */ - zisofs->pz_offset += bytes; + zisofs->pz_offset += (uint32_t)bytes; return (bytes); } avail = rs; @@ -7942,9 +7976,9 @@ zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs, if (avail > zisofs->block_avail) zisofs->stream.avail_in = zisofs->block_avail; else - zisofs->stream.avail_in = avail; + zisofs->stream.avail_in = (uInt)avail; zisofs->stream.next_out = wb_buffptr(a); - zisofs->stream.avail_out = wb_remaining(a); + zisofs->stream.avail_out = (uInt)wb_remaining(a); r = inflate(&zisofs->stream, 0); switch (r) { @@ -7957,12 +7991,12 @@ zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs, return (ARCHIVE_FATAL); } avail -= zisofs->stream.next_in - p; - zisofs->block_avail -= zisofs->stream.next_in - p; + zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p); r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out); if (r < 0) return (r); } - zisofs->pz_offset += bytes; + zisofs->pz_offset += (uint32_t)bytes; return (bytes - avail); } @@ -7996,7 +8030,7 @@ zisofs_rewind_boot_file(struct archive_write *a) fd = iso9660->temp_fd; new_offset = wb_offset(a); read_offset = file->content.offset_of_temp; - remaining = file->content.size; + remaining = (size_t)file->content.size; if (remaining > 1024 * 32) rbuff_size = 1024 * 32; else diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c index 3802a25f3..9c0613c9b 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c @@ -1,6 +1,6 @@ /*- - * Copyright (c) 2009,2011 Michihiro NAKAJIMA * Copyright (c) 2008 Joerg Sonnenberger + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,6 +38,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171 #include "archive_crypto_private.h" #include "archive_entry.h" #include "archive_private.h" +#include "archive_rb.h" +#include "archive_string.h" #include "archive_write_private.h" #define INDENTNAMELEN 15 @@ -45,27 +47,39 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171 #define SET_KEYS \ (F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME) -struct mtree_entry { - struct mtree_entry *next; +struct attr_counter { + struct attr_counter *prev; + struct attr_counter *next; + struct mtree_entry *m_entry; + int count; +}; - char *pathname; - char *symlink; - unsigned int nlink; - mode_t filetype; - mode_t mode; - int64_t uid; - int64_t gid; - char *uname; - char *gname; - char *fflags_text; - unsigned long fflags_set; - unsigned long fflags_clear; - time_t mtime; - long mtime_nsec; - dev_t rdevmajor; - dev_t rdevminor; - int64_t size; +struct att_counter_set { + struct attr_counter *uid_list; + struct attr_counter *gid_list; + struct attr_counter *mode_list; + struct attr_counter *flags_list; +}; + +struct mtree_chain { + struct mtree_entry *first; + struct mtree_entry **last; +}; + +/* + * The Data only for a directory file. + */ +struct dir_info { + struct archive_rb_tree rbtree; + struct mtree_chain children; + struct mtree_entry *chnext; + int virtual; +}; +/* + * The Data only for a regular file. + */ +struct reg_info { int compute_sum; uint32_t crc; #ifdef ARCHIVE_HAS_MD5 @@ -88,23 +102,51 @@ struct mtree_entry { #endif }; -struct attr_counter { - struct attr_counter *prev; - struct attr_counter *next; - int count; - struct mtree_entry *m_entry; +struct mtree_entry { + struct archive_rb_node rbnode; + struct mtree_entry *next; + struct mtree_entry *parent; + struct dir_info *dir_info; + struct reg_info *reg_info; + + struct archive_string parentdir; + struct archive_string basename; + struct archive_string pathname; + struct archive_string symlink; + struct archive_string uname; + struct archive_string gname; + struct archive_string fflags_text; + unsigned int nlink; + mode_t filetype; + mode_t mode; + int64_t size; + int64_t uid; + int64_t gid; + time_t mtime; + long mtime_nsec; + unsigned long fflags_set; + unsigned long fflags_clear; + dev_t rdevmajor; + dev_t rdevminor; }; struct mtree_writer { struct mtree_entry *mtree_entry; + struct mtree_entry *root; + struct mtree_entry *cur_dirent; + struct archive_string cur_dirstr; + struct mtree_chain file_list; + struct archive_string ebuf; struct archive_string buf; int first; uint64_t entry_bytes_remaining; + + /* + * Set global value. + */ struct { - int output; - int processed; - struct archive_string parent; + int processing; mode_t type; int keys; int64_t uid; @@ -112,14 +154,11 @@ struct mtree_writer { mode_t mode; unsigned long fflags_set; unsigned long fflags_clear; - - struct attr_counter *uid_list; - struct attr_counter *gid_list; - struct attr_counter *mode_list; - struct attr_counter *flags_list; - struct mtree_entry *me_first; - struct mtree_entry **me_last; } set; + struct att_counter_set acs; + int classic; + int depth; + /* check sum */ int compute_sum; uint32_t crc; @@ -173,27 +212,51 @@ struct mtree_writer { #define F_SHA512 0x02000000 /* SHA-512 digest */ /* Options */ - int dironly; /* if the dironly is 1, ignore everything except - * directory type files. like mtree(8) -d option. - */ - int indent; /* if the indent is 1, indent writing data. */ + int dironly; /* If it is set, ignore all files except + * directory files, like mtree(8) -d option. */ + int indent; /* If it is set, indent output data. */ + int output_global_set; /* If it is set, use /set keyword to set + * global values. When generating mtree + * classic format, it is set by default. */ }; #define DEFAULT_KEYS (F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\ | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\ | F_UNAME) +#define attr_counter_set_reset attr_counter_set_free -static struct attr_counter * new_attr_count(struct mtree_entry *, - struct attr_counter *); -static void free_attr_count(struct attr_counter **); -static int inc_attr_count(struct attr_counter **, struct attr_counter *, +static void attr_counter_free(struct attr_counter **); +static int attr_counter_inc(struct attr_counter **, struct attr_counter *, struct attr_counter *, struct mtree_entry *); -static int collect_set_values(struct mtree_writer *, struct mtree_entry *); -static int get_keys(struct mtree_writer *, struct mtree_entry *); +static struct attr_counter * attr_counter_new(struct mtree_entry *, + struct attr_counter *); +static int attr_counter_set_collect(struct mtree_writer *, + struct mtree_entry *); +static void attr_counter_set_free(struct mtree_writer *); +static int get_global_set_keys(struct mtree_writer *, struct mtree_entry *); +static int mtree_entry_add_child_tail(struct mtree_entry *, + struct mtree_entry *); +static int mtree_entry_create_virtual_dir(struct archive_write *, const char *, + struct mtree_entry **); +static int mtree_entry_cmp_node(const struct archive_rb_node *, + const struct archive_rb_node *); +static int mtree_entry_cmp_key(const struct archive_rb_node *, const void *); +static int mtree_entry_exchange_same_entry(struct archive_write *, + struct mtree_entry *, struct mtree_entry *); +static void mtree_entry_free(struct mtree_entry *); +static int mtree_entry_new(struct archive_write *, struct archive_entry *, + struct mtree_entry **); +static void mtree_entry_register_free(struct mtree_writer *); +static void mtree_entry_register_init(struct mtree_writer *); +static int mtree_entry_setup_filenames(struct archive_write *, + struct mtree_entry *, struct archive_entry *); +static int mtree_entry_tree_add(struct archive_write *, struct mtree_entry **); static void sum_init(struct mtree_writer *); static void sum_update(struct mtree_writer *, const void *, size_t); -static void sum_final(struct mtree_writer *, struct mtree_entry *); -static void sum_write(struct archive_string *, struct mtree_entry *); +static void sum_final(struct mtree_writer *, struct reg_info *); +static void sum_write(struct archive_string *, struct reg_info *); +static int write_mtree_entry(struct archive_write *, struct mtree_entry *); +static int write_dot_dot_entry(struct archive_write *, struct mtree_entry *); #define COMPUTE_CRC(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)] static const uint32_t crctab[] = { @@ -251,26 +314,30 @@ static const uint32_t crctab[] = { 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 }; -static int -mtree_safe_char(char c) -{ - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) - return 1; - if (c >= '0' && c <= '9') - return 1; - if (c == 35 || c == 61 || c == 92) - return 0; /* #, = and \ are always quoted */ - - if (c >= 33 && c <= 47) /* !"$%&'()*+,-./ */ - return 1; - if (c >= 58 && c <= 64) /* :;<>?@ */ - return 1; - if (c >= 91 && c <= 96) /* []^_` */ - return 1; - if (c >= 123 && c <= 126) /* {|}~ */ - return 1; - return 0; -} +static const unsigned char safe_char[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */ + /* !"$%&'()*+,-./ EXCLUSION:0x20( ) 0x23(#) */ + 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ + /* 0123456789:;<>? EXCLUSION:0x3d(=) */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */ + /* @ABCDEFGHIJKLMNO */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ + /* PQRSTUVWXYZ[]^_ EXCLUSION:0x5c(\) */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 50 - 5F */ + /* `abcdefghijklmno */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ + /* pqrstuvwxyz{|}~ */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ +}; static void mtree_quote(struct archive_string *s, const char *str) @@ -280,7 +347,7 @@ mtree_quote(struct archive_string *s, const char *str) unsigned char c; for (start = str; *str != '\0'; ++str) { - if (mtree_safe_char(*str)) + if (safe_char[*(const unsigned char *)str]) continue; if (start != str) archive_strncat(s, start, str - start); @@ -303,9 +370,19 @@ mtree_quote(struct archive_string *s, const char *str) static void mtree_indent(struct mtree_writer *mtree) { - int i, fn; + int i, fn, nd, pd; const char *r, *s, *x; + if (mtree->classic) { + if (mtree->indent) { + nd = 0; + pd = mtree->depth * 4; + } else { + nd = mtree->depth?4:0; + pd = 0; + } + } else + nd = pd = 0; fn = 1; s = r = mtree->ebuf.s; x = NULL; @@ -314,37 +391,46 @@ mtree_indent(struct mtree_writer *mtree) while ((r = strchr(r, ' ')) != NULL) { if (fn) { fn = 0; + for (i = 0; i < nd + pd; i++) + archive_strappend_char(&mtree->buf, ' '); archive_strncat(&mtree->buf, s, r - s); - if (r -s > INDENTNAMELEN) { + if (nd + (r -s) > INDENTNAMELEN) { archive_strncat(&mtree->buf, " \\\n", 3); - for (i = 0; i < (INDENTNAMELEN + 1); i++) + for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++) archive_strappend_char(&mtree->buf, ' '); } else { - for (i = r -s; i < (INDENTNAMELEN + 1); i++) + for (i = (int)(r -s + nd); + i < (INDENTNAMELEN + 1); i++) archive_strappend_char(&mtree->buf, ' '); } s = ++r; x = NULL; continue; } - if (r - s <= MAXLINELEN - 3 - INDENTNAMELEN) + if (pd + (r - s) <= MAXLINELEN - 3 - INDENTNAMELEN) x = r++; else { if (x == NULL) x = r; archive_strncat(&mtree->buf, s, x - s); archive_strncat(&mtree->buf, " \\\n", 3); - for (i = 0; i < (INDENTNAMELEN + 1); i++) + for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++) archive_strappend_char(&mtree->buf, ' '); s = r = ++x; x = NULL; } } - if (x != NULL && strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) { + if (fn) { + for (i = 0; i < nd + pd; i++) + archive_strappend_char(&mtree->buf, ' '); + archive_strcat(&mtree->buf, s); + s += strlen(s); + } + if (x != NULL && pd + strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) { /* Last keyword is longer. */ archive_strncat(&mtree->buf, s, x - s); archive_strncat(&mtree->buf, " \\\n", 3); - for (i = 0; i < (INDENTNAMELEN + 1); i++) + for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++) archive_strappend_char(&mtree->buf, ' '); s = ++x; } @@ -352,163 +438,70 @@ mtree_indent(struct mtree_writer *mtree) archive_string_empty(&mtree->ebuf); } -#if !defined(_WIN32) || defined(__CYGWIN__) -static size_t -dir_len(struct mtree_entry *me) -{ - const char *path, *r; - - path = me->pathname; - r = strrchr(path, '/'); - if (r == NULL) - return (0); - /* Include a separator size */ - return (r - path + 1); -} - -#else /* _WIN32 && !__CYGWIN__ */ -/* - * Note: We should use wide-character for findng '\' character, - * a directory separator on Windows, because some character-set have - * been using the '\' character for a part of its multibyte character - * code. - */ -static size_t -dir_len(struct mtree_entry *me) -{ - wchar_t wc; - const char *path; - const char *p, *rp; - size_t al, l, size; - - path = me->pathname; - al = l = -1; - for (p = path; *p != '\0'; ++p) { - if (*p == '\\') - al = l = p - path; - else if (*p == '/') - al = p - path; - } - if (l == -1) - goto alen; - size = p - path; - rp = p = path; - while (*p != '\0') { - l = mbtowc(&wc, p, size); - if (l == -1) - goto alen; - if (l == 1 && (wc == L'/' || wc == L'\\')) - rp = p; - p += l; - size -= l; - } - return (rp - path + 1); -alen: - if (al == -1) - return (0); - return (al + 1); -} -#endif /* _WIN32 && !__CYGWIN__ */ - -/* - * Test if a parent directory of the current entry is changed. - */ -static int -parent_dir_changed(struct archive_string *dir, struct mtree_entry *me) -{ - const char *path; - size_t l; - - l = dir_len(me); - path = me->pathname; - if (archive_strlen(dir) > 0) { - if (l == 0) { - archive_string_empty(dir); - return (1); - } - if (strncmp(dir->s, path, l) == 0) - return (0); /* The parent directory is the same. */ - } else if (l == 0) - return (0); /* The parent directory is the same. */ - archive_strncpy(dir, path, l); - return (1); -} - /* * Write /set keyword. * Set most used value of uid,gid,mode and fflags, which are - * collected by collect_set_values() function. + * collected by attr_counter_set_collect() function. */ static void write_global(struct mtree_writer *mtree) { struct archive_string setstr; struct archive_string unsetstr; - const char *name; + struct att_counter_set *acs; int keys, oldkeys, effkeys; - struct attr_counter *ac; archive_string_init(&setstr); archive_string_init(&unsetstr); keys = mtree->keys & SET_KEYS; oldkeys = mtree->set.keys; effkeys = keys; - if (mtree->set.processed) { + acs = &mtree->acs; + if (mtree->set.processing) { /* * Check if the global data needs updating. */ effkeys &= ~F_TYPE; - if (oldkeys & (F_UNAME | F_UID)) { - ac = mtree->set.uid_list; - do { - if (mtree->set.uid == ac->m_entry->uid) { - effkeys &= ~(F_UNAME | F_UID); - break; - } - if (ac->next != NULL && - ac->next->count == ac->count) - continue; - } while (0); + if (acs->uid_list == NULL) + effkeys &= ~(F_UNAME | F_UID); + else if (oldkeys & (F_UNAME | F_UID)) { + if (acs->uid_list->count < 2 || + mtree->set.uid == acs->uid_list->m_entry->uid) + effkeys &= ~(F_UNAME | F_UID); } - if (oldkeys & (F_GNAME | F_GID)) { - ac = mtree->set.gid_list; - do { - if (mtree->set.gid == ac->m_entry->gid) { - effkeys &= ~(F_GNAME | F_GID); - break; - } - if (ac->next != NULL && - ac->next->count == ac->count) - continue; - } while (0); + if (acs->gid_list == NULL) + effkeys &= ~(F_GNAME | F_GID); + else if (oldkeys & (F_GNAME | F_GID)) { + if (acs->gid_list->count < 2 || + mtree->set.gid == acs->gid_list->m_entry->gid) + effkeys &= ~(F_GNAME | F_GID); } - if (oldkeys & F_MODE) { - ac = mtree->set.mode_list; - do { - if (mtree->set.mode == ac->m_entry->mode) { - effkeys &= ~F_MODE; - break; - } - if (ac->next != NULL && - ac->next->count == ac->count) - continue; - } while (0); + if (acs->mode_list == NULL) + effkeys &= ~F_MODE; + else if (oldkeys & F_MODE) { + if (acs->mode_list->count < 2 || + mtree->set.mode == acs->mode_list->m_entry->mode) + effkeys &= ~F_MODE; } - if ((oldkeys & F_FLAGS) != 0) { - ac = mtree->set.flags_list; - do { - if (ac->m_entry->fflags_set == - mtree->set.fflags_set && - ac->m_entry->fflags_clear == - mtree->set.fflags_clear) { - effkeys &= ~F_FLAGS; - break; - } - if (ac->next != NULL && - ac->next->count == ac->count) - continue; - } while (0); + if (acs->flags_list == NULL) + effkeys &= ~F_FLAGS; + else if ((oldkeys & F_FLAGS) != 0) { + if (acs->flags_list->count < 2 || + (acs->flags_list->m_entry->fflags_set == + mtree->set.fflags_set && + acs->flags_list->m_entry->fflags_clear == + mtree->set.fflags_clear)) + effkeys &= ~F_FLAGS; } + } else { + if (acs->uid_list == NULL) + keys &= ~(F_UNAME | F_UID); + if (acs->gid_list == NULL) + keys &= ~(F_GNAME | F_GID); + if (acs->mode_list == NULL) + keys &= ~F_MODE; + if (acs->flags_list == NULL) + keys &= ~F_FLAGS; } if ((keys & effkeys & F_TYPE) != 0) { if (mtree->dironly) { @@ -520,10 +513,9 @@ write_global(struct mtree_writer *mtree) } } if ((keys & effkeys & F_UNAME) != 0) { - name = mtree->set.uid_list->m_entry->uname; - if (name != NULL) { + if (archive_strlen(&(acs->uid_list->m_entry->uname)) > 0) { archive_strcat(&setstr, " uname="); - mtree_quote(&setstr, name); + mtree_quote(&setstr, acs->uid_list->m_entry->uname.s); } else { keys &= ~F_UNAME; if ((oldkeys & F_UNAME) != 0) @@ -531,15 +523,14 @@ write_global(struct mtree_writer *mtree) } } if ((keys & effkeys & F_UID) != 0) { - mtree->set.uid = mtree->set.uid_list->m_entry->uid; + mtree->set.uid = acs->uid_list->m_entry->uid; archive_string_sprintf(&setstr, " uid=%jd", (intmax_t)mtree->set.uid); } if ((keys & effkeys & F_GNAME) != 0) { - name = mtree->set.gid_list->m_entry->gname; - if (name != NULL) { + if (archive_strlen(&(acs->gid_list->m_entry->gname)) > 0) { archive_strcat(&setstr, " gname="); - mtree_quote(&setstr, name); + mtree_quote(&setstr, acs->gid_list->m_entry->gname.s); } else { keys &= ~F_GNAME; if ((oldkeys & F_GNAME) != 0) @@ -547,24 +538,25 @@ write_global(struct mtree_writer *mtree) } } if ((keys & effkeys & F_GID) != 0) { - mtree->set.gid = mtree->set.gid_list->m_entry->gid; + mtree->set.gid = acs->gid_list->m_entry->gid; archive_string_sprintf(&setstr, " gid=%jd", (intmax_t)mtree->set.gid); } if ((keys & effkeys & F_MODE) != 0) { - mtree->set.mode = mtree->set.mode_list->m_entry->mode; + mtree->set.mode = acs->mode_list->m_entry->mode; archive_string_sprintf(&setstr, " mode=%o", (unsigned int)mtree->set.mode); } if ((keys & effkeys & F_FLAGS) != 0) { - name = mtree->set.flags_list->m_entry->fflags_text; - if (name != NULL) { + if (archive_strlen( + &(acs->flags_list->m_entry->fflags_text)) > 0) { archive_strcat(&setstr, " flags="); - mtree_quote(&setstr, name); + mtree_quote(&setstr, + acs->flags_list->m_entry->fflags_text.s); mtree->set.fflags_set = - mtree->set.flags_list->m_entry->fflags_set; + acs->flags_list->m_entry->fflags_set; mtree->set.fflags_clear = - mtree->set.flags_list->m_entry->fflags_clear; + acs->flags_list->m_entry->fflags_clear; } else { keys &= ~F_FLAGS; if ((oldkeys & F_FLAGS) != 0) @@ -578,16 +570,11 @@ write_global(struct mtree_writer *mtree) archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s); archive_string_free(&setstr); mtree->set.keys = keys; - mtree->set.processed = 1; - - free_attr_count(&mtree->set.uid_list); - free_attr_count(&mtree->set.gid_list); - free_attr_count(&mtree->set.mode_list); - free_attr_count(&mtree->set.flags_list); + mtree->set.processing = 1; } static struct attr_counter * -new_attr_count(struct mtree_entry *me, struct attr_counter *prev) +attr_counter_new(struct mtree_entry *me, struct attr_counter *prev) { struct attr_counter *ac; @@ -602,7 +589,7 @@ new_attr_count(struct mtree_entry *me, struct attr_counter *prev) } static void -free_attr_count(struct attr_counter **top) +attr_counter_free(struct attr_counter **top) { struct attr_counter *ac, *tac; @@ -618,7 +605,7 @@ free_attr_count(struct attr_counter **top) } static int -inc_attr_count(struct attr_counter **top, struct attr_counter *ac, +attr_counter_inc(struct attr_counter **top, struct attr_counter *ac, struct attr_counter *last, struct mtree_entry *me) { struct attr_counter *pac; @@ -647,7 +634,7 @@ inc_attr_count(struct attr_counter **top, struct attr_counter *ac, ac->next->prev = ac; } } else { - ac = new_attr_count(me, last); + ac = attr_counter_new(me, last); if (ac == NULL) return (-1); last->next = ac; @@ -655,93 +642,99 @@ inc_attr_count(struct attr_counter **top, struct attr_counter *ac, return (0); } +/* + * Tabulate uid,gid,mode and fflags of a entry in order to be used for /set. + */ static int -collect_set_values(struct mtree_writer *mtree, struct mtree_entry *me) +attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me) { - int keys = mtree->keys; struct attr_counter *ac, *last; + struct att_counter_set *acs = &mtree->acs; + int keys = mtree->keys; if (keys & (F_UNAME | F_UID)) { - if (mtree->set.uid_list == NULL) { - mtree->set.uid_list = new_attr_count(me, NULL); - if (mtree->set.uid_list == NULL) + if (acs->uid_list == NULL) { + acs->uid_list = attr_counter_new(me, NULL); + if (acs->uid_list == NULL) return (-1); } else { last = NULL; - for (ac = mtree->set.uid_list; ac; ac = ac->next) { + for (ac = acs->uid_list; ac; ac = ac->next) { if (ac->m_entry->uid == me->uid) break; last = ac; } - if (inc_attr_count( - &mtree->set.uid_list, ac, last, me) < 0) + if (attr_counter_inc(&acs->uid_list, ac, last, me) < 0) return (-1); } } if (keys & (F_GNAME | F_GID)) { - if (mtree->set.gid_list == NULL) { - mtree->set.gid_list = new_attr_count(me, NULL); - if (mtree->set.gid_list == NULL) + if (acs->gid_list == NULL) { + acs->gid_list = attr_counter_new(me, NULL); + if (acs->gid_list == NULL) return (-1); } else { last = NULL; - for (ac = mtree->set.gid_list; ac; ac = ac->next) { + for (ac = acs->gid_list; ac; ac = ac->next) { if (ac->m_entry->gid == me->gid) break; last = ac; } - if (inc_attr_count( - &mtree->set.gid_list, ac, last, me) < 0) + if (attr_counter_inc(&acs->gid_list, ac, last, me) < 0) return (-1); } } if (keys & F_MODE) { - if (mtree->set.mode_list == NULL) { - mtree->set.mode_list = new_attr_count(me, NULL); - if (mtree->set.mode_list == NULL) + if (acs->mode_list == NULL) { + acs->mode_list = attr_counter_new(me, NULL); + if (acs->mode_list == NULL) return (-1); } else { last = NULL; - for (ac = mtree->set.mode_list; ac; ac = ac->next) { + for (ac = acs->mode_list; ac; ac = ac->next) { if (ac->m_entry->mode == me->mode) break; last = ac; } - if (inc_attr_count( - &mtree->set.mode_list, ac, last, me) < 0) + if (attr_counter_inc(&acs->mode_list, ac, last, me) < 0) return (-1); } } if (keys & F_FLAGS) { - if (mtree->set.flags_list == NULL) { - mtree->set.flags_list = new_attr_count(me, NULL); - if (mtree->set.flags_list == NULL) + if (acs->flags_list == NULL) { + acs->flags_list = attr_counter_new(me, NULL); + if (acs->flags_list == NULL) return (-1); } else { last = NULL; - for (ac = mtree->set.flags_list; ac; ac = ac->next) { + for (ac = acs->flags_list; ac; ac = ac->next) { if (ac->m_entry->fflags_set == me->fflags_set && - ac->m_entry->fflags_clear == me->fflags_clear) + ac->m_entry->fflags_clear == + me->fflags_clear) break; last = ac; } - if (inc_attr_count( - &mtree->set.flags_list, ac, last, me) < 0) + if (attr_counter_inc(&acs->flags_list, ac, last, me) < 0) return (-1); } } - /* - * Save a entry. - */ - me->next = NULL; - *mtree->set.me_last = me; - mtree->set.me_last = &me->next; return (0); } +static void +attr_counter_set_free(struct mtree_writer *mtree) +{ + struct att_counter_set *acs = &mtree->acs; + + attr_counter_free(&acs->uid_list); + attr_counter_free(&acs->gid_list); + attr_counter_free(&acs->mode_list); + attr_counter_free(&acs->flags_list); +} + static int -get_keys(struct mtree_writer *mtree, struct mtree_entry *me) +get_global_set_keys(struct mtree_writer *mtree, struct mtree_entry *me) { int keys; @@ -788,56 +781,92 @@ get_keys(struct mtree_writer *mtree, struct mtree_entry *me) return (keys); } -static struct mtree_entry * -new_mtree_entry(struct archive_entry *entry) +static int +mtree_entry_new(struct archive_write *a, struct archive_entry *entry, + struct mtree_entry **m_entry) { struct mtree_entry *me; const char *s; + int r; + static const struct archive_rb_tree_ops rb_ops = { + mtree_entry_cmp_node, mtree_entry_cmp_key + }; me = calloc(1, sizeof(*me)); - if (me == NULL) - return (NULL); - me->pathname = strdup(archive_entry_pathname(entry)); + if (me == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a mtree entry"); + *m_entry = NULL; + return (ARCHIVE_FATAL); + } + + r = mtree_entry_setup_filenames(a, me, entry); + if (r < ARCHIVE_WARN) { + mtree_entry_free(me); + *m_entry = NULL; + return (r); + } + if ((s = archive_entry_symlink(entry)) != NULL) - me->symlink = strdup(s); - else - me->symlink = NULL; + archive_strcpy(&me->symlink, s); me->nlink = archive_entry_nlink(entry); me->filetype = archive_entry_filetype(entry); me->mode = archive_entry_mode(entry) & 07777; me->uid = archive_entry_uid(entry); me->gid = archive_entry_gid(entry); if ((s = archive_entry_uname(entry)) != NULL) - me->uname = strdup(s); - else - me->uname = NULL; + archive_strcpy(&me->uname, s); if ((s = archive_entry_gname(entry)) != NULL) - me->gname = strdup(s); - else - me->gname = NULL; + archive_strcpy(&me->gname, s); if ((s = archive_entry_fflags_text(entry)) != NULL) - me->fflags_text = strdup(s); - else - me->fflags_text = NULL; + archive_strcpy(&me->fflags_text, s); archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear); me->mtime = archive_entry_mtime(entry); me->mtime_nsec = archive_entry_mtime_nsec(entry); me->rdevmajor = archive_entry_rdevmajor(entry); me->rdevminor = archive_entry_rdevminor(entry); me->size = archive_entry_size(entry); - me->compute_sum = 0; + if (me->filetype == AE_IFDIR) { + me->dir_info = calloc(1, sizeof(*me->dir_info)); + if (me->dir_info == NULL) { + mtree_entry_free(me); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a mtree entry"); + *m_entry = NULL; + return (ARCHIVE_FATAL); + } + __archive_rb_tree_init(&me->dir_info->rbtree, &rb_ops); + me->dir_info->children.first = NULL; + me->dir_info->children.last = &(me->dir_info->children.first); + me->dir_info->chnext = NULL; + } else if (me->filetype == AE_IFREG) { + me->reg_info = calloc(1, sizeof(*me->reg_info)); + if (me->reg_info == NULL) { + mtree_entry_free(me); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a mtree entry"); + *m_entry = NULL; + return (ARCHIVE_FATAL); + } + me->reg_info->compute_sum = 0; + } - return (me); + *m_entry = me; + return (ARCHIVE_OK); } static void -free_mtree_entry(struct mtree_entry *me) +mtree_entry_free(struct mtree_entry *me) { - free(me->pathname); - free(me->symlink); - free(me->uname); - free(me->gname); - free(me->fflags_text); + archive_string_free(&me->parentdir); + archive_string_free(&me->basename); + archive_string_free(&me->pathname); + archive_string_free(&me->symlink); + archive_string_free(&me->uname); + archive_string_free(&me->gname); + archive_string_free(&me->fflags_text); + free(me->dir_info); + free(me->reg_info); free(me); } @@ -846,66 +875,100 @@ archive_write_mtree_header(struct archive_write *a, struct archive_entry *entry) { struct mtree_writer *mtree= a->format_data; + struct mtree_entry *mtree_entry; + int r, r2; if (mtree->first) { mtree->first = 0; archive_strcat(&mtree->buf, "#mtree\n"); if ((mtree->keys & SET_KEYS) == 0) - mtree->set.output = 0;/* Disalbed. */ + mtree->output_global_set = 0;/* Disalbed. */ } mtree->entry_bytes_remaining = archive_entry_size(entry); + + /* While directory only mode, we do not handle non directory files. */ if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR) return (ARCHIVE_OK); - mtree->mtree_entry = new_mtree_entry(entry); - if (mtree->mtree_entry == NULL) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate mtree entry"); - return (ARCHIVE_FATAL); + r2 = mtree_entry_new(a, entry, &mtree_entry); + if (r2 < ARCHIVE_WARN) + return (r2); + r = mtree_entry_tree_add(a, &mtree_entry); + if (r < ARCHIVE_WARN) { + mtree_entry_free(mtree_entry); + return (r); } + mtree->mtree_entry = mtree_entry; - mtree->compute_sum = 0; - - /* If current file is not a regular file, we do not have to - * compute the sum of its content. */ - if (archive_entry_filetype(entry) != AE_IFREG) - return (ARCHIVE_OK); - - /* Initialize a bunch of sum check context. */ - sum_init(mtree); + /* If the current file is a regular file, we have to + * compute the sum of its content. + * Initialize a bunch of sum check context. */ + if (mtree_entry->reg_info) + sum_init(mtree); - return (ARCHIVE_OK); + return (r2); } static int -write_entry(struct archive_write *a, struct mtree_entry *me) +write_mtree_entry(struct archive_write *a, struct mtree_entry *me) { struct mtree_writer *mtree = a->format_data; struct archive_string *str; int keys, ret; + if (me->dir_info) { + if (mtree->classic) { + /* + * Output a comment line to describe the full + * pathname of the entry as mtree utility does + * while generating classic format. + */ + if (!mtree->dironly) + archive_strappend_char(&mtree->buf, '\n'); + if (me->parentdir.s) + archive_string_sprintf(&mtree->buf, + "# %s/%s\n", + me->parentdir.s, me->basename.s); + else + archive_string_sprintf(&mtree->buf, + "# %s\n", + me->basename.s); + } + if (mtree->output_global_set) + write_global(mtree); + } archive_string_empty(&mtree->ebuf); - str = (mtree->indent)? &mtree->ebuf : &mtree->buf; - mtree_quote(str, me->pathname); - keys = get_keys(mtree, me); + str = (mtree->indent || mtree->classic)? &mtree->ebuf : &mtree->buf; + + if (!mtree->classic && me->parentdir.s) { + /* + * If generating format is not classic one(v1), output + * a full pathname. + */ + mtree_quote(str, me->parentdir.s); + archive_strappend_char(str, '/'); + } + mtree_quote(str, me->basename.s); + + keys = get_global_set_keys(mtree, me); if ((keys & F_NLINK) != 0 && me->nlink != 1 && me->filetype != AE_IFDIR) archive_string_sprintf(str, " nlink=%u", me->nlink); - if ((keys & F_GNAME) != 0 && me->gname != NULL) { + if ((keys & F_GNAME) != 0 && archive_strlen(&me->gname) > 0) { archive_strcat(str, " gname="); - mtree_quote(str, me->gname); + mtree_quote(str, me->gname.s); } - if ((keys & F_UNAME) != 0 && me->uname != NULL) { + if ((keys & F_UNAME) != 0 && archive_strlen(&me->uname) > 0) { archive_strcat(str, " uname="); - mtree_quote(str, me->uname); + mtree_quote(str, me->uname.s); } if ((keys & F_FLAGS) != 0) { - if (me->fflags_text != NULL) { + if (archive_strlen(&me->fflags_text) > 0) { archive_strcat(str, " flags="); - mtree_quote(str, me->fflags_text); - } else if (mtree->set.processed && + mtree_quote(str, me->fflags_text.s); + } else if (mtree->set.processing && (mtree->set.keys & F_FLAGS) != 0) /* Overwrite the global parameter. */ archive_strcat(str, " flags=none"); @@ -926,7 +989,7 @@ write_entry(struct archive_write *a, struct mtree_entry *me) archive_strcat(str, " type=link"); if ((keys & F_SLINK) != 0) { archive_strcat(str, " link="); - mtree_quote(str, me->symlink); + mtree_quote(str, me->symlink.s); } break; case AE_IFSOCK: @@ -972,15 +1035,48 @@ write_entry(struct archive_write *a, struct mtree_entry *me) } /* Write a bunch of sum. */ - if (me->filetype == AE_IFREG) - sum_write(str, me); + if (me->reg_info) + sum_write(str, me->reg_info); + + archive_strappend_char(str, '\n'); + if (mtree->indent || mtree->classic) + mtree_indent(mtree); + + if (mtree->buf.length > 32768) { + ret = __archive_write_output( + a, mtree->buf.s, mtree->buf.length); + archive_string_empty(&mtree->buf); + } else + ret = ARCHIVE_OK; + return (ret); +} - archive_strcat(str, "\n"); - if (mtree->indent) +static int +write_dot_dot_entry(struct archive_write *a, struct mtree_entry *n) +{ + struct mtree_writer *mtree = a->format_data; + int ret; + + if (n->parentdir.s) { + if (mtree->indent) { + int i, pd = mtree->depth * 4; + for (i = 0; i < pd; i++) + archive_strappend_char(&mtree->buf, ' '); + } + archive_string_sprintf(&mtree->buf, "# %s/%s\n", + n->parentdir.s, n->basename.s); + } + + if (mtree->indent) { + archive_string_empty(&mtree->ebuf); + archive_strncat(&mtree->ebuf, "..\n\n", (mtree->dironly)?3:4); mtree_indent(mtree); + } else + archive_strncat(&mtree->buf, "..\n\n", (mtree->dironly)?3:4); if (mtree->buf.length > 32768) { - ret = __archive_write_output(a, mtree->buf.s, mtree->buf.length); + ret = __archive_write_output( + a, mtree->buf.s, mtree->buf.length); archive_string_empty(&mtree->buf); } else ret = ARCHIVE_OK; @@ -988,29 +1084,106 @@ write_entry(struct archive_write *a, struct mtree_entry *me) } /* - * Write mtree entries saved at collect_set_values() function. + * Write mtree entries saved at attr_counter_set_collect() function. */ static int -write_mtree_entries(struct archive_write *a) +write_mtree_entry_tree(struct archive_write *a) { struct mtree_writer *mtree = a->format_data; - struct mtree_entry *me, *tme; + struct mtree_entry *np = mtree->root; + struct archive_rb_node *n; int ret; - for (me = mtree->set.me_first; me; me = me->next) { - ret = write_entry(a, me); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); - } + do { + if (mtree->output_global_set) { + /* + * Collect attribute infomation to know which value + * is frequently used among the children. + */ + attr_counter_set_reset(mtree); + ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) { + struct mtree_entry *e = (struct mtree_entry *)n; + if (attr_counter_set_collect(mtree, e) < 0) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + } + } + if (!np->dir_info->virtual || mtree->classic) { + ret = write_mtree_entry(a, np); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + /* Whenever output_global_set is enabled + * output global value(/set keywords) + * even if the directory entry is not allowd + * to be written because the global values + * can be used for the children. */ + if (mtree->output_global_set) + write_global(mtree); + } + /* + * Output the attribute of all files except directory files. + */ + mtree->depth++; + ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) { + struct mtree_entry *e = (struct mtree_entry *)n; + + if (e->dir_info) + mtree_entry_add_child_tail(np, e); + else { + ret = write_mtree_entry(a, e); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + } + mtree->depth--; + + if (np->dir_info->children.first != NULL) { + /* + * Descend the tree. + */ + np = np->dir_info->children.first; + if (mtree->indent) + mtree->depth++; + continue; + } else if (mtree->classic) { + /* + * While printing mtree classic, if there are not + * any directory files(except "." and "..") in the + * directory, output two dots ".." as returning + * the parent directory. + */ + ret = write_dot_dot_entry(a, np); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + while (np != np->parent) { + if (np->dir_info->chnext == NULL) { + /* + * Ascend the tree; go back to the parent. + */ + if (mtree->indent) + mtree->depth--; + if (mtree->classic) { + ret = write_dot_dot_entry(a, + np->parent); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + np = np->parent; + } else { + /* + * Switch to next mtree entry in the directory. + */ + np = np->dir_info->chnext; + break; + } + } + } while (np != np->parent); - me = mtree->set.me_first; - while (me != NULL) { - tme = me->next; - free_mtree_entry(me); - me = tme; - } - mtree->set.me_first = NULL; - mtree->set.me_last = &mtree->set.me_first; return (ARCHIVE_OK); } @@ -1019,40 +1192,15 @@ archive_write_mtree_finish_entry(struct archive_write *a) { struct mtree_writer *mtree = a->format_data; struct mtree_entry *me; - int ret; if ((me = mtree->mtree_entry) == NULL) return (ARCHIVE_OK); mtree->mtree_entry = NULL; - if (me->filetype == AE_IFREG) - sum_final(mtree, me); + if (me->reg_info) + sum_final(mtree, me->reg_info); - if (mtree->set.output) { - if (!mtree->dironly) { - if (archive_strlen(&mtree->set.parent) == 0) - parent_dir_changed(&mtree->set.parent, me); - if (parent_dir_changed(&mtree->set.parent, me)) { - /* Write /set keyword */ - write_global(mtree); - /* Write entries saved by - * collect_set_values() function. */ - ret = write_mtree_entries(a); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); - } - } - /* Tabulate uid,gid,mode and fflags of a entry - * in order to be used for /set. and, at this time - * we do not write a entry. */ - collect_set_values(mtree, me); - return (ARCHIVE_OK); - } else { - /* Write the current entry and free it. */ - ret = write_entry(a, me); - free_mtree_entry(me); - } - return (ret == ARCHIVE_OK ? ret : ARCHIVE_FATAL); + return (ARCHIVE_OK); } static int @@ -1061,9 +1209,8 @@ archive_write_mtree_close(struct archive_write *a) struct mtree_writer *mtree= a->format_data; int ret; - if (mtree->set.output && mtree->set.me_first != NULL) { - write_global(mtree); - ret = write_mtree_entries(a); + if (mtree->root != NULL) { + ret = write_mtree_entry_tree(a); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); } @@ -1079,7 +1226,7 @@ archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n) struct mtree_writer *mtree= a->format_data; if (n > mtree->entry_bytes_remaining) - n = mtree->entry_bytes_remaining; + n = (size_t)mtree->entry_bytes_remaining; mtree->entry_bytes_remaining -= n; /* We don't need to compute a regular file sum */ @@ -1096,25 +1243,16 @@ static int archive_write_mtree_free(struct archive_write *a) { struct mtree_writer *mtree= a->format_data; - struct mtree_entry *me, *tme; if (mtree == NULL) return (ARCHIVE_OK); /* Make sure we dot not leave any entries. */ - me = mtree->set.me_first; - while (me != NULL) { - tme = me->next; - free_mtree_entry(me); - me = tme; - } + mtree_entry_register_free(mtree); + archive_string_free(&mtree->cur_dirstr); archive_string_free(&mtree->ebuf); archive_string_free(&mtree->buf); - archive_string_free(&mtree->set.parent); - free_attr_count(&mtree->set.uid_list); - free_attr_count(&mtree->set.gid_list); - free_attr_count(&mtree->set.mode_list); - free_attr_count(&mtree->set.flags_list); + attr_counter_set_free(mtree); free(mtree); a->format_data = NULL; return (ARCHIVE_OK); @@ -1209,7 +1347,7 @@ archive_write_mtree_options(struct archive_write *a, const char *key, else if (strcmp(key, "uname") == 0) keybit = F_UNAME; else if (strcmp(key, "use-set") == 0) { - mtree->set.output = (value != NULL)? 1: 0; + mtree->output_global_set = (value != NULL)? 1: 0; return (ARCHIVE_OK); } break; @@ -1222,17 +1360,19 @@ archive_write_mtree_options(struct archive_write *a, const char *key, return (ARCHIVE_OK); } - return (ARCHIVE_FAILED); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } -int -archive_write_set_format_mtree(struct archive *_a) +static int +archive_write_set_format_mtree_default(struct archive *_a, const char *fn) { struct archive_write *a = (struct archive_write *)_a; struct mtree_writer *mtree; - archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, - ARCHIVE_STATE_NEW, "archive_write_set_format_mtree"); + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, fn); if (a->format_free != NULL) (a->format_free)(a); @@ -1246,14 +1386,12 @@ archive_write_set_format_mtree(struct archive *_a) mtree->mtree_entry = NULL; mtree->first = 1; memset(&(mtree->set), 0, sizeof(mtree->set)); - archive_string_init(&mtree->set.parent); mtree->keys = DEFAULT_KEYS; mtree->dironly = 0; mtree->indent = 0; archive_string_init(&mtree->ebuf); archive_string_init(&mtree->buf); - mtree->set.me_first = NULL; - mtree->set.me_last = &mtree->set.me_first; + mtree_entry_register_init(mtree); a->format_data = mtree; a->format_free = archive_write_mtree_free; a->format_name = "mtree"; @@ -1268,9 +1406,41 @@ archive_write_set_format_mtree(struct archive *_a) return (ARCHIVE_OK); } +int +archive_write_set_format_mtree(struct archive *_a) +{ + return archive_write_set_format_mtree_default(_a, + "archive_write_set_format_mtree"); +} + +int +archive_write_set_format_mtree_classic(struct archive *_a) +{ + int r; + + r = archive_write_set_format_mtree_default(_a, + "archive_write_set_format_mtree_classic"); + if (r == ARCHIVE_OK) { + struct archive_write *a = (struct archive_write *)_a; + struct mtree_writer *mtree; + + mtree = (struct mtree_writer *)a->format_data; + + /* Set to output a mtree archive in classic format. */ + mtree->classic = 1; + /* Basically, mtree classic format uses '/set' global + * value. */ + mtree->output_global_set = 1; + } + return (r); +} + static void sum_init(struct mtree_writer *mtree) { + + mtree->compute_sum = 0; + if (mtree->keys & F_CKSUM) { mtree->compute_sum |= F_CKSUM; mtree->crc = 0; @@ -1367,7 +1537,7 @@ sum_update(struct mtree_writer *mtree, const void *buff, size_t n) } static void -sum_final(struct mtree_writer *mtree, struct mtree_entry *me) +sum_final(struct mtree_writer *mtree, struct reg_info *reg) { if (mtree->compute_sum & F_CKSUM) { @@ -1375,34 +1545,34 @@ sum_final(struct mtree_writer *mtree, struct mtree_entry *me) /* Include the length of the file. */ for (len = mtree->crc_len; len != 0; len >>= 8) COMPUTE_CRC(mtree->crc, len & 0xff); - me->crc = ~mtree->crc; + reg->crc = ~mtree->crc; } #ifdef ARCHIVE_HAS_MD5 if (mtree->compute_sum & F_MD5) - archive_md5_final(&mtree->md5ctx, me->buf_md5); + archive_md5_final(&mtree->md5ctx, reg->buf_md5); #endif #ifdef ARCHIVE_HAS_RMD160 if (mtree->compute_sum & F_RMD160) - archive_rmd160_final(&mtree->rmd160ctx, me->buf_rmd160); + archive_rmd160_final(&mtree->rmd160ctx, reg->buf_rmd160); #endif #ifdef ARCHIVE_HAS_SHA1 if (mtree->compute_sum & F_SHA1) - archive_sha1_final(&mtree->sha1ctx, me->buf_sha1); + archive_sha1_final(&mtree->sha1ctx, reg->buf_sha1); #endif #ifdef ARCHIVE_HAS_SHA256 if (mtree->compute_sum & F_SHA256) - archive_sha256_final(&mtree->sha256ctx, me->buf_sha256); + archive_sha256_final(&mtree->sha256ctx, reg->buf_sha256); #endif #ifdef ARCHIVE_HAS_SHA384 if (mtree->compute_sum & F_SHA384) - archive_sha384_final(&mtree->sha384ctx, me->buf_sha384); + archive_sha384_final(&mtree->sha384ctx, reg->buf_sha384); #endif #ifdef ARCHIVE_HAS_SHA512 if (mtree->compute_sum & F_SHA512) - archive_sha512_final(&mtree->sha512ctx, me->buf_sha512); + archive_sha512_final(&mtree->sha512ctx, reg->buf_sha512); #endif /* Save what types of sum are computed. */ - me->compute_sum = mtree->compute_sum; + reg->compute_sum = mtree->compute_sum; } #if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \ @@ -1422,47 +1592,612 @@ strappend_bin(struct archive_string *s, const unsigned char *bin, int n) #endif static void -sum_write(struct archive_string *str, struct mtree_entry *me) +sum_write(struct archive_string *str, struct reg_info *reg) { - if (me->compute_sum & F_CKSUM) { + if (reg->compute_sum & F_CKSUM) { archive_string_sprintf(str, " cksum=%ju", - (uintmax_t)me->crc); + (uintmax_t)reg->crc); } #ifdef ARCHIVE_HAS_MD5 - if (me->compute_sum & F_MD5) { + if (reg->compute_sum & F_MD5) { archive_strcat(str, " md5digest="); - strappend_bin(str, me->buf_md5, sizeof(me->buf_md5)); + strappend_bin(str, reg->buf_md5, sizeof(reg->buf_md5)); } #endif #ifdef ARCHIVE_HAS_RMD160 - if (me->compute_sum & F_RMD160) { + if (reg->compute_sum & F_RMD160) { archive_strcat(str, " rmd160digest="); - strappend_bin(str, me->buf_rmd160, sizeof(me->buf_rmd160)); + strappend_bin(str, reg->buf_rmd160, sizeof(reg->buf_rmd160)); } #endif #ifdef ARCHIVE_HAS_SHA1 - if (me->compute_sum & F_SHA1) { + if (reg->compute_sum & F_SHA1) { archive_strcat(str, " sha1digest="); - strappend_bin(str, me->buf_sha1, sizeof(me->buf_sha1)); + strappend_bin(str, reg->buf_sha1, sizeof(reg->buf_sha1)); } #endif #ifdef ARCHIVE_HAS_SHA256 - if (me->compute_sum & F_SHA256) { + if (reg->compute_sum & F_SHA256) { archive_strcat(str, " sha256digest="); - strappend_bin(str, me->buf_sha256, sizeof(me->buf_sha256)); + strappend_bin(str, reg->buf_sha256, sizeof(reg->buf_sha256)); } #endif #ifdef ARCHIVE_HAS_SHA384 - if (me->compute_sum & F_SHA384) { + if (reg->compute_sum & F_SHA384) { archive_strcat(str, " sha384digest="); - strappend_bin(str, me->buf_sha384, sizeof(me->buf_sha384)); + strappend_bin(str, reg->buf_sha384, sizeof(reg->buf_sha384)); } #endif #ifdef ARCHIVE_HAS_SHA512 - if (me->compute_sum & F_SHA512) { + if (reg->compute_sum & F_SHA512) { archive_strcat(str, " sha512digest="); - strappend_bin(str, me->buf_sha512, sizeof(me->buf_sha512)); + strappend_bin(str, reg->buf_sha512, sizeof(reg->buf_sha512)); + } +#endif +} + +static int +mtree_entry_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct mtree_entry *e1 = (const struct mtree_entry *)n1; + const struct mtree_entry *e2 = (const struct mtree_entry *)n2; + + return (strcmp(e2->basename.s, e1->basename.s)); +} + +static int +mtree_entry_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct mtree_entry *e = (const struct mtree_entry *)n; + + return (strcmp((const char *)key, e->basename.s)); +} + +#if defined(_WIN32) || defined(__CYGWIN__) +static int +cleanup_backslash_1(char *p) +{ + int mb, dos; + + mb = dos = 0; + while (*p) { + if (*(unsigned char *)p > 127) + mb = 1; + if (*p == '\\') { + /* If we have not met any multi-byte characters, + * we can replace '\' with '/'. */ + if (!mb) + *p = '/'; + dos = 1; + } + p++; + } + if (!mb || !dos) + return (0); + return (-1); +} + +static void +cleanup_backslash_2(wchar_t *p) +{ + + /* Convert a path-separator from '\' to '/' */ + while (*p != L'\0') { + if (*p == L'\\') + *p = L'/'; + p++; + } +} +#endif + +/* + * Generate a parent directory name and a base name from a pathname. + */ +static int +mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file, + struct archive_entry *entry) +{ + const char *pathname; + char *p, *dirname, *slash; + size_t len; + int ret = ARCHIVE_OK; + + archive_strcpy(&file->pathname, archive_entry_pathname(entry)); +#if defined(_WIN32) || defined(__CYGWIN__) + /* + * Convert a path-separator from '\' to '/' + */ + if (cleanup_backslash_1(file->pathname.s) != 0) { + const wchar_t *wp = archive_entry_pathname_w(entry); + struct archive_wstring ws; + + if (wp != NULL) { + int r; + archive_string_init(&ws); + archive_wstrcpy(&ws, wp); + cleanup_backslash_2(ws.s); + archive_string_empty(&(file->pathname)); + r = archive_string_append_from_wcs(&(file->pathname), + ws.s, ws.length); + archive_wstring_free(&ws); + if (r < 0 && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + } + } +#else + (void)a; /* UNUSED */ +#endif + pathname = file->pathname.s; + if (strcmp(pathname, ".") == 0) { + archive_strcpy(&file->basename, "."); + return (ARCHIVE_OK); + } + + archive_strcpy(&(file->parentdir), pathname); + + len = file->parentdir.length; + p = dirname = file->parentdir.s; + + /* + * Remove leading '/' and '../' elements + */ + while (*p) { + if (p[0] == '/') { + p++; + len--; + } else if (p[0] != '.') + break; + else if (p[1] == '.' && p[2] == '/') { + p += 3; + len -= 3; + } else + break; + } + if (p != dirname) { + memmove(dirname, p, len+1); + p = dirname; + } + /* + * Remove "/","/." and "/.." elements from tail. + */ + while (len > 0) { + size_t ll = len; + + if (len > 0 && p[len-1] == '/') { + p[len-1] = '\0'; + len--; + } + if (len > 1 && p[len-2] == '/' && p[len-1] == '.') { + p[len-2] = '\0'; + len -= 2; + } + if (len > 2 && p[len-3] == '/' && p[len-2] == '.' && + p[len-1] == '.') { + p[len-3] = '\0'; + len -= 3; + } + if (ll == len) + break; + } + while (*p) { + if (p[0] == '/') { + if (p[1] == '/') + /* Convert '//' --> '/' */ + strcpy(p, p+1); + else if (p[1] == '.' && p[2] == '/') + /* Convert '/./' --> '/' */ + strcpy(p, p+2); + else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { + /* Convert 'dir/dir1/../dir2/' + * --> 'dir/dir2/' + */ + char *rp = p -1; + while (rp >= dirname) { + if (*rp == '/') + break; + --rp; + } + if (rp > dirname) { + strcpy(rp, p+3); + p = rp; + } else { + strcpy(dirname, p+4); + p = dirname; + } + } else + p++; + } else + p++; + } + p = dirname; + len = strlen(p); + + /* + * Add "./" prefiex. + * NOTE: If the pathname does not have a path separator, we have + * to add "./" to the head of the pathename because mtree reader + * will suppose that it is v1(a.k.a classic) mtree format and + * change the directory unexpectedly and so it will make a wrong + * path. + */ + if (strcmp(p, ".") != 0 && strncmp(p, "./", 2) != 0) { + struct archive_string as; + archive_string_init(&as); + archive_strcpy(&as, "./"); + archive_strncat(&as, p, len); + archive_string_empty(&file->parentdir); + archive_string_concat(&file->parentdir, &as); + archive_string_free(&as); + p = file->parentdir.s; + len = archive_strlen(&file->parentdir); + } + + /* + * Find out the position which points the last position of + * path separator('/'). + */ + slash = NULL; + for (; *p != '\0'; p++) { + if (*p == '/') + slash = p; + } + if (slash == NULL) { + /* The pathname doesn't have a parent directory. */ + file->parentdir.length = len; + archive_string_copy(&(file->basename), &(file->parentdir)); + archive_string_empty(&(file->parentdir)); + *file->parentdir.s = '\0'; + return (ret); + } + + /* Make a basename from dirname and slash */ + *slash = '\0'; + file->parentdir.length = slash - dirname; + archive_strcpy(&(file->basename), slash + 1); + return (ret); +} + +static int +mtree_entry_create_virtual_dir(struct archive_write *a, const char *pathname, + struct mtree_entry **m_entry) +{ + struct archive_entry *entry; + struct mtree_entry *file; + int r; + + entry = archive_entry_new(); + if (entry == NULL) { + *m_entry = NULL; + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); } + archive_entry_copy_pathname(entry, pathname); + archive_entry_set_mode(entry, AE_IFDIR | 0755); + archive_entry_set_mtime(entry, time(NULL), 0); + + r = mtree_entry_new(a, entry, &file); + archive_entry_free(entry); + if (r < ARCHIVE_WARN) { + *m_entry = NULL; + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + file->dir_info->virtual = 1; + + *m_entry = file; + return (ARCHIVE_OK); +} + +static void +mtree_entry_register_add(struct mtree_writer *mtree, struct mtree_entry *file) +{ + file->next = NULL; + *mtree->file_list.last = file; + mtree->file_list.last = &(file->next); +} + +static void +mtree_entry_register_init(struct mtree_writer *mtree) +{ + mtree->file_list.first = NULL; + mtree->file_list.last = &(mtree->file_list.first); +} + +static void +mtree_entry_register_free(struct mtree_writer *mtree) +{ + struct mtree_entry *file, *file_next; + + file = mtree->file_list.first; + while (file != NULL) { + file_next = file->next; + mtree_entry_free(file); + file = file_next; + } +} + +static int +mtree_entry_add_child_tail(struct mtree_entry *parent, + struct mtree_entry *child) +{ + child->dir_info->chnext = NULL; + *parent->dir_info->children.last = child; + parent->dir_info->children.last = &(child->dir_info->chnext); + return (1); +} + +/* + * Find a entry from a parent entry with the name. + */ +static struct mtree_entry * +mtree_entry_find_child(struct mtree_entry *parent, const char *child_name) +{ + struct mtree_entry *np; + + if (parent == NULL) + return (NULL); + np = (struct mtree_entry *)__archive_rb_tree_find_node( + &(parent->dir_info->rbtree), child_name); + return (np); +} + +static int +get_path_component(char *name, size_t n, const char *fn) +{ + char *p; + size_t l; + + p = strchr(fn, '/'); + if (p == NULL) { + if ((l = strlen(fn)) == 0) + return (0); + } else + l = p - fn; + if (l > n -1) + return (-1); + memcpy(name, fn, l); + name[l] = '\0'; + + return ((int)l); +} + +/* + * Add a new entry into the tree. + */ +static int +mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char name[_MAX_FNAME];/* Included null terminator size. */ +#elif defined(NAME_MAX) && NAME_MAX >= 255 + char name[NAME_MAX+1]; +#else + char name[256]; #endif + struct mtree_writer *mtree = (struct mtree_writer *)a->format_data; + struct mtree_entry *dent, *file, *np; + const char *fn, *p; + int l, r; + + file = *filep; + if (file->parentdir.length == 0 && file->basename.length == 1 && + file->basename.s[0] == '.') { + file->parent = file; + if (mtree->root != NULL) { + np = mtree->root; + goto same_entry; + } + mtree->root = file; + mtree_entry_register_add(mtree, file); + return (ARCHIVE_OK); + } + + if (file->parentdir.length == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal programing error " + "in generating canonical name for %s", + file->pathname.s); + return (ARCHIVE_FAILED); + } + + fn = p = file->parentdir.s; + + /* + * If the path of the parent directory of `file' entry is + * the same as the path of `cur_dirent', add `file' entry to + * `cur_dirent'. + */ + if (archive_strlen(&(mtree->cur_dirstr)) + == archive_strlen(&(file->parentdir)) && + strcmp(mtree->cur_dirstr.s, fn) == 0) { + if (!__archive_rb_tree_insert_node( + &(mtree->cur_dirent->dir_info->rbtree), + (struct archive_rb_node *)file)) { + /* There is the same name in the tree. */ + np = (struct mtree_entry *)__archive_rb_tree_find_node( + &(mtree->cur_dirent->dir_info->rbtree), + file->basename.s); + goto same_entry; + } + file->parent = mtree->cur_dirent; + mtree_entry_register_add(mtree, file); + return (ARCHIVE_OK); + } + + dent = mtree->root; + for (;;) { + l = get_path_component(name, sizeof(name), fn); + if (l == 0) { + np = NULL; + break; + } + if (l < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + return (ARCHIVE_FATAL); + } + if (l == 1 && name[0] == '.' && dent != NULL && + dent == mtree->root) { + fn += l; + if (fn[0] == '/') + fn++; + continue; + } + + np = mtree_entry_find_child(dent, name); + if (np == NULL || fn[0] == '\0') + break; + + /* Find next sub directory. */ + if (!np->dir_info) { + /* NOT Directory! */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "`%s' is not directory, we cannot insert `%s' ", + np->pathname.s, file->pathname.s); + return (ARCHIVE_FAILED); + } + fn += l; + if (fn[0] == '/') + fn++; + dent = np; + } + if (np == NULL) { + /* + * Create virtual parent directories. + */ + while (fn[0] != '\0') { + struct mtree_entry *vp; + struct archive_string as; + + archive_string_init(&as); + archive_strncat(&as, p, fn - p + l); + if (as.s[as.length-1] == '/') { + as.s[as.length-1] = '\0'; + as.length--; + } + r = mtree_entry_create_virtual_dir(a, as.s, &vp); + archive_string_free(&as); + if (r < ARCHIVE_WARN) + return (r); + + if (strcmp(vp->pathname.s, ".") == 0) { + vp->parent = vp; + mtree->root = vp; + } else { + __archive_rb_tree_insert_node( + &(dent->dir_info->rbtree), + (struct archive_rb_node *)vp); + vp->parent = dent; + } + mtree_entry_register_add(mtree, vp); + np = vp; + + fn += l; + if (fn[0] == '/') + fn++; + l = get_path_component(name, sizeof(name), fn); + if (l < 0) { + archive_string_free(&as); + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + return (ARCHIVE_FATAL); + } + dent = np; + } + + /* Found out the parent directory where `file' can be + * inserted. */ + mtree->cur_dirent = dent; + archive_string_empty(&(mtree->cur_dirstr)); + archive_string_ensure(&(mtree->cur_dirstr), + archive_strlen(&(dent->parentdir)) + + archive_strlen(&(dent->basename)) + 2); + if (archive_strlen(&(dent->parentdir)) + + archive_strlen(&(dent->basename)) == 0) + mtree->cur_dirstr.s[0] = 0; + else { + if (archive_strlen(&(dent->parentdir)) > 0) { + archive_string_copy(&(mtree->cur_dirstr), + &(dent->parentdir)); + archive_strappend_char( + &(mtree->cur_dirstr), '/'); + } + archive_string_concat(&(mtree->cur_dirstr), + &(dent->basename)); + } + + if (!__archive_rb_tree_insert_node( + &(dent->dir_info->rbtree), + (struct archive_rb_node *)file)) { + np = (struct mtree_entry *)__archive_rb_tree_find_node( + &(dent->dir_info->rbtree), file->basename.s); + goto same_entry; + } + file->parent = dent; + mtree_entry_register_add(mtree, file); + return (ARCHIVE_OK); + } + +same_entry: + /* + * We have already has the entry the filename of which is + * the same. + */ + r = mtree_entry_exchange_same_entry(a, np, file); + if (r < ARCHIVE_WARN) + return (r); + if (np->dir_info) + np->dir_info->virtual = 0; + *filep = np; + mtree_entry_free(file); + return (ARCHIVE_WARN); +} + +static int +mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np, + struct mtree_entry *file) +{ + + if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Found duplicate entries `%s' and its file type is " + "different", + np->pathname.s); + return (ARCHIVE_FAILED); + } + + /* Update the existent mtree entry's attributes by the new one's. */ + archive_string_empty(&np->symlink); + archive_string_concat(&np->symlink, &file->symlink); + archive_string_empty(&np->uname); + archive_string_concat(&np->uname, &file->uname); + archive_string_empty(&np->gname); + archive_string_concat(&np->gname, &file->gname); + archive_string_empty(&np->fflags_text); + archive_string_concat(&np->fflags_text, &file->fflags_text); + np->nlink = file->nlink; + np->filetype = file->filetype; + np->mode = file->mode; + np->size = file->size; + np->uid = file->uid; + np->gid = file->gid; + np->fflags_set = file->fflags_set; + np->fflags_clear = file->fflags_clear; + np->mtime = file->mtime; + np->mtime_nsec = file->mtime_nsec; + np->rdevmajor = file->rdevmajor; + np->rdevminor = file->rdevminor; + + return (ARCHIVE_WARN); } diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c index 8affb2c15..687f8e48a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle - * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -187,11 +187,13 @@ archive_write_pax_options(struct archive_write *a, const char *key, } else archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "pax: invalid charset name"); - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "pax: unknown keyword ``%s''", key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } /* @@ -332,8 +334,7 @@ archive_write_pax_header_xattrs(struct archive_write *a, url_encoded_name = url_encode(name); if (url_encoded_name != NULL) { /* Convert narrow-character to UTF-8. */ - r = archive_strcpy_in_locale( - &(pax->l_url_encoded_name), + r = archive_strcpy_l(&(pax->l_url_encoded_name), url_encoded_name, pax->sconv_utf8); free(url_encoded_name); /* Done with this. */ if (r == 0) @@ -463,7 +464,6 @@ archive_write_pax_header(struct archive_write *a, { struct archive_entry *entry_main; const char *p; - char *t; const char *suffix; int need_extension, r, ret; int sparse_count; @@ -541,24 +541,73 @@ archive_write_pax_header(struct archive_write *a, case AE_IFREG: break; case AE_IFDIR: + { /* * Ensure a trailing '/'. Modify the original * entry so the client sees the change. */ - p = archive_entry_pathname(entry_original); - if (p[strlen(p) - 1] != '/') { - t = (char *)malloc(strlen(p) + 2); - if (t == NULL) { +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry_original); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { archive_set_error(&a->archive, ENOMEM, - "Can't allocate pax data"); + "Can't allocate pax data"); + archive_wstring_free(&ws); return(ARCHIVE_FATAL); } - strcpy(t, p); - strcat(t, "/"); - archive_entry_copy_pathname(entry_original, t); - free(t); + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w( + entry_original, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry_original); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate pax data"); + archive_string_free(&as); + return(ARCHIVE_FATAL); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname( + entry_original, as.s); + archive_string_free(&as); } break; + } case AE_IFSOCK: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -576,7 +625,7 @@ archive_write_pax_header(struct archive_write *a, /* * If Mac OS metadata blob is here, recurse to write that - * as a separate entry. This is realy a pretty poor design: + * as a separate entry. This is really a pretty poor design: * In particular, it doubles the overhead for long filenames. * TODO: Help Apple folks design something better and figure * out how to transition from this legacy format. @@ -598,8 +647,10 @@ archive_write_pax_header(struct archive_write *a, oname = archive_entry_pathname(entry_original); name_length = strlen(oname); name = malloc(name_length + 3); - if (name == NULL) { + if (name == NULL || extra == NULL) { /* XXX error message */ + archive_entry_free(extra); + free(name); return (ARCHIVE_FAILED); } strcpy(name, oname); @@ -638,11 +689,13 @@ archive_write_pax_header(struct archive_write *a, /* Recurse to write the special copyfile entry. */ r = archive_write_pax_header(a, extra); + archive_entry_free(extra); if (r < ARCHIVE_WARN) return (r); if (r < ret) ret = r; - r = archive_write_pax_data(a, mac_metadata, mac_metadata_size); + r = (int)archive_write_pax_data(a, mac_metadata, + mac_metadata_size); if (r < ARCHIVE_WARN) return (r); if (r < ret) @@ -655,7 +708,20 @@ archive_write_pax_header(struct archive_write *a, } /* Copy entry so we can modify it as needed. */ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry_original); + if (entry_main == entry_original) + entry_main = archive_entry_clone(entry_original); +#else entry_main = archive_entry_clone(entry_original); +#endif + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate pax data"); + return(ARCHIVE_FATAL); + } archive_string_empty(&(pax->pax_header)); /* Blank our work area. */ archive_string_empty(&(pax->sparse_map)); sparse_total = 0; @@ -1261,7 +1327,7 @@ archive_write_pax_header(struct archive_write *a, return (ARCHIVE_FATAL); } /* Pad out the end of the entry. */ - r = __archive_write_nulls(a, pax->entry_padding); + r = __archive_write_nulls(a, (size_t)pax->entry_padding); if (r != ARCHIVE_OK) { /* If a write fails, we're pretty much toast. */ return (ARCHIVE_FATAL); @@ -1439,7 +1505,7 @@ build_ustar_entry_name(char *dest, const char *src, size_t src_length, * * Joerg Schilling has argued that this is unnecessary because, in * practice, if the pax extended attributes get extracted as regular - * files, noone is going to bother reading those attributes to + * files, no one is going to bother reading those attributes to * manually restore them. Based on this, 'star' uses * /tmp/PaxHeader/'basename' as the ustar header name. This is a * tempting argument, in part because it's simpler than the SUSv3 @@ -1596,13 +1662,14 @@ archive_write_pax_finish_entry(struct archive_write *a) if (remaining == 0) { while (pax->sparse_list) { struct sparse_block *sb; - remaining += pax->sparse_list->remaining; + if (!pax->sparse_list->is_hole) + remaining += pax->sparse_list->remaining; sb = pax->sparse_list->next; free(pax->sparse_list); pax->sparse_list = sb; } } - ret = __archive_write_nulls(a, remaining + pax->entry_padding); + ret = __archive_write_nulls(a, (size_t)(remaining + pax->entry_padding)); pax->entry_bytes_remaining = pax->entry_padding = 0; return (ret); } @@ -1647,9 +1714,9 @@ archive_write_pax_data(struct archive_write *a, const void *buff, size_t s) return (total); p = ((const unsigned char *)buff) + total; - ws = s; + ws = s - total; if (ws > pax->sparse_list->remaining) - ws = pax->sparse_list->remaining; + ws = (size_t)pax->sparse_list->remaining; if (pax->sparse_list->is_hole) { /* Current block is hole thus we do not write @@ -1799,7 +1866,7 @@ _sparse_list_add_block(struct pax *pax, int64_t offset, int64_t length, sb->is_hole = is_hole; sb->offset = offset; sb->remaining = length; - if (pax->sparse_list == NULL) + if (pax->sparse_list == NULL || pax->sparse_tail == NULL) pax->sparse_list = pax->sparse_tail = sb; else { pax->sparse_tail->next = sb; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c index 4b96ac23c..484ab34b2 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -224,11 +224,13 @@ archive_write_ustar_options(struct archive_write *a, const char *key, else ret = ARCHIVE_FATAL; } - } else - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: unknown keyword ``%s''", a->format_name, key); + return (ret); + } - return (ret); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -237,6 +239,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) char buff[512]; int ret, ret2; struct ustar *ustar; + struct archive_entry *entry_main; struct archive_string_conv *sconv; ustar = (struct ustar *)a->format_data; @@ -267,37 +270,106 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) if (AE_IFDIR == archive_entry_filetype(entry)) { const char *p; - char *t; + size_t path_length; /* * Ensure a trailing '/'. Modify the entry so * the client sees the change. */ - p = archive_entry_pathname(entry); - if (p[strlen(p) - 1] != '/') { - t = (char *)malloc(strlen(p) + 2); - if (t == NULL) { +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + archive_wstring_free(&ws); + return(ARCHIVE_FATAL); + } + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w(entry, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { archive_set_error(&a->archive, ENOMEM, - "Can't allocate ustar data"); + "Can't allocate ustar data"); + archive_string_free(&as); return(ARCHIVE_FATAL); } - strcpy(t, p); - strcat(t, "/"); - archive_entry_copy_pathname(entry, t); - free(t); +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname(entry, as.s); + archive_string_free(&as); } } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate ustar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1, sconv); - if (ret < ARCHIVE_WARN) + if (ret < ARCHIVE_WARN) { + if (entry_main) + archive_entry_free(entry_main); return (ret); + } ret2 = __archive_write_output(a, buff, 512); - if (ret2 < ARCHIVE_WARN) + if (ret2 < ARCHIVE_WARN) { + if (entry_main) + archive_entry_free(entry_main); return (ret2); + } if (ret2 < ret) ret = ret2; ustar->entry_bytes_remaining = archive_entry_size(entry); ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining); + if (entry_main) + archive_entry_free(entry_main); return (ret); } @@ -670,7 +742,7 @@ archive_write_ustar_finish_entry(struct archive_write *a) ustar = (struct ustar *)a->format_data; ret = __archive_write_nulls(a, - ustar->entry_bytes_remaining + ustar->entry_padding); + (size_t)(ustar->entry_bytes_remaining + ustar->entry_padding)); ustar->entry_bytes_remaining = ustar->entry_padding = 0; return (ret); } @@ -683,7 +755,7 @@ archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s) ustar = (struct ustar *)a->format_data; if (s > ustar->entry_bytes_remaining) - s = ustar->entry_bytes_remaining; + s = (size_t)ustar->entry_bytes_remaining; ret = __archive_write_output(a, buff, s); ustar->entry_bytes_remaining -= s; if (ret != ARCHIVE_OK) diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c new file mode 100644 index 000000000..17efbaf75 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c @@ -0,0 +1,661 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <stdio.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_write_private.h" + +struct v7tar { + uint64_t entry_bytes_remaining; + uint64_t entry_padding; + + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_default; + int init_default_conversion; +}; + +/* + * Define structure of POSIX 'v7tar' tar header. + */ +#define V7TAR_name_offset 0 +#define V7TAR_name_size 100 +#define V7TAR_mode_offset 100 +#define V7TAR_mode_size 6 +#define V7TAR_mode_max_size 8 +#define V7TAR_uid_offset 108 +#define V7TAR_uid_size 6 +#define V7TAR_uid_max_size 8 +#define V7TAR_gid_offset 116 +#define V7TAR_gid_size 6 +#define V7TAR_gid_max_size 8 +#define V7TAR_size_offset 124 +#define V7TAR_size_size 11 +#define V7TAR_size_max_size 12 +#define V7TAR_mtime_offset 136 +#define V7TAR_mtime_size 11 +#define V7TAR_mtime_max_size 12 +#define V7TAR_checksum_offset 148 +#define V7TAR_checksum_size 8 +#define V7TAR_typeflag_offset 156 +#define V7TAR_typeflag_size 1 +#define V7TAR_linkname_offset 157 +#define V7TAR_linkname_size 100 +#define V7TAR_padding_offset 257 +#define V7TAR_padding_size 255 + +/* + * A filled-in copy of the header for initialization. + */ +static const char template_header[] = { + /* name: 100 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0, + /* Mode, space-null termination: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* uid, space-null termination: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* gid, space-null termination: 8 bytes */ + '0','0','0','0','0','0', ' ','\0', + /* size, space termation: 12 bytes */ + '0','0','0','0','0','0','0','0','0','0','0', ' ', + /* mtime, space termation: 12 bytes */ + '0','0','0','0','0','0','0','0','0','0','0', ' ', + /* Initial checksum value: 8 spaces */ + ' ',' ',' ',' ',' ',' ',' ',' ', + /* Typeflag: 1 byte */ + 0, + /* Linkname: 100 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0, + /* Padding: 255 bytes */ + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0 +}; + +static ssize_t archive_write_v7tar_data(struct archive_write *a, const void *buff, + size_t s); +static int archive_write_v7tar_free(struct archive_write *); +static int archive_write_v7tar_close(struct archive_write *); +static int archive_write_v7tar_finish_entry(struct archive_write *); +static int archive_write_v7tar_header(struct archive_write *, + struct archive_entry *entry); +static int archive_write_v7tar_options(struct archive_write *, + const char *, const char *); +static int format_256(int64_t, char *, int); +static int format_number(int64_t, char *, int size, int max, int strict); +static int format_octal(int64_t, char *, int); +static int format_header_v7tar(struct archive_write *, char h[512], + struct archive_entry *, int, struct archive_string_conv *); + +/* + * Set output format to 'v7tar' format. + */ +int +archive_write_set_format_v7tar(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct v7tar *v7tar; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_v7tar"); + + /* If someone else was already registered, unregister them. */ + if (a->format_free != NULL) + (a->format_free)(a); + + /* Basic internal sanity test. */ + if (sizeof(template_header) != 512) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal: template_header wrong size: %zu should be 512", + sizeof(template_header)); + return (ARCHIVE_FATAL); + } + + v7tar = (struct v7tar *)malloc(sizeof(*v7tar)); + if (v7tar == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate v7tar data"); + return (ARCHIVE_FATAL); + } + memset(v7tar, 0, sizeof(*v7tar)); + a->format_data = v7tar; + a->format_name = "tar (non-POSIX)"; + a->format_options = archive_write_v7tar_options; + a->format_write_header = archive_write_v7tar_header; + a->format_write_data = archive_write_v7tar_data; + a->format_close = archive_write_v7tar_close; + a->format_free = archive_write_v7tar_free; + a->format_finish_entry = archive_write_v7tar_finish_entry; + a->archive.archive_format = ARCHIVE_FORMAT_TAR; + a->archive.archive_format_name = "tar (non-POSIX)"; + return (ARCHIVE_OK); +} + +static int +archive_write_v7tar_options(struct archive_write *a, const char *key, + const char *val) +{ + struct v7tar *v7tar = (struct v7tar *)a->format_data; + int ret = ARCHIVE_FAILED; + + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: hdrcharset option needs a character-set name", + a->format_name); + else { + v7tar->opt_sconv = archive_string_conversion_to_charset( + &a->archive, val, 0); + if (v7tar->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry) +{ + char buff[512]; + int ret, ret2; + struct v7tar *v7tar; + struct archive_entry *entry_main; + struct archive_string_conv *sconv; + + v7tar = (struct v7tar *)a->format_data; + + /* Setup default string conversion. */ + if (v7tar->opt_sconv == NULL) { + if (!v7tar->init_default_conversion) { + v7tar->sconv_default = + archive_string_default_conversion_for_write( + &(a->archive)); + v7tar->init_default_conversion = 1; + } + sconv = v7tar->sconv_default; + } else + sconv = v7tar->opt_sconv; + + /* Sanity check. */ + if (archive_entry_pathname(entry) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't record entry in tar file without pathname"); + return (ARCHIVE_FAILED); + } + + /* Only regular files (not hardlinks) have data. */ + if (archive_entry_hardlink(entry) != NULL || + archive_entry_symlink(entry) != NULL || + !(archive_entry_filetype(entry) == AE_IFREG)) + archive_entry_set_size(entry, 0); + + if (AE_IFDIR == archive_entry_filetype(entry)) { + const char *p; + size_t path_length; + /* + * Ensure a trailing '/'. Modify the entry so + * the client sees the change. + */ +#if defined(_WIN32) && !defined(__CYGWIN__) + const wchar_t *wp; + + wp = archive_entry_pathname_w(entry); + if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + struct archive_wstring ws; + + archive_string_init(&ws); + path_length = wcslen(wp); + if (archive_wstring_ensure(&ws, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate v7tar data"); + archive_wstring_free(&ws); + return(ARCHIVE_FATAL); + } + /* Should we keep '\' ? */ + if (wp[path_length -1] == L'\\') + path_length--; + archive_wstrncpy(&ws, wp, path_length); + archive_wstrappend_wchar(&ws, L'/'); + archive_entry_copy_pathname_w(entry, ws.s); + archive_wstring_free(&ws); + p = NULL; + } else +#endif + p = archive_entry_pathname(entry); + /* + * On Windows, this is a backup operation just in + * case getting WCS failed. On POSIX, this is a + * normal operation. + */ + if (p != NULL && p[strlen(p) - 1] != '/') { + struct archive_string as; + + archive_string_init(&as); + path_length = strlen(p); + if (archive_string_ensure(&as, + path_length + 2) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate v7tar data"); + archive_string_free(&as); + return(ARCHIVE_FATAL); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* NOTE: This might break the pathname + * if the current code page is CP932 and + * the pathname includes a character '\' + * as a part of its multibyte pathname. */ + if (p[strlen(p) -1] == '\\') + path_length--; + else +#endif + archive_strncpy(&as, p, path_length); + archive_strappend_char(&as, '/'); + archive_entry_copy_pathname(entry, as.s); + archive_string_free(&as); + } + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + entry_main = __la_win_entry_in_posix_pathseparator(entry); + if (entry_main == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate v7tar data"); + return(ARCHIVE_FATAL); + } + if (entry != entry_main) + entry = entry_main; + else + entry_main = NULL; +#else + entry_main = NULL; +#endif + ret = format_header_v7tar(a, buff, entry, 1, sconv); + if (ret < ARCHIVE_WARN) { + if (entry_main) + archive_entry_free(entry_main); + return (ret); + } + ret2 = __archive_write_output(a, buff, 512); + if (ret2 < ARCHIVE_WARN) { + if (entry_main) + archive_entry_free(entry_main); + return (ret2); + } + if (ret2 < ret) + ret = ret2; + + v7tar->entry_bytes_remaining = archive_entry_size(entry); + v7tar->entry_padding = 0x1ff & (-(int64_t)v7tar->entry_bytes_remaining); + if (entry_main) + archive_entry_free(entry_main); + return (ret); +} + +/* + * Format a basic 512-byte "v7tar" header. + * + * Returns -1 if format failed (due to field overflow). + * Note that this always formats as much of the header as possible. + * If "strict" is set to zero, it will extend numeric fields as + * necessary (overwriting terminators or using base-256 extensions). + * + */ +static int +format_header_v7tar(struct archive_write *a, char h[512], + struct archive_entry *entry, int strict, + struct archive_string_conv *sconv) +{ + unsigned int checksum; + int i, r, ret; + size_t copy_length; + const char *p, *pp; + int mytartype; + + ret = 0; + mytartype = -1; + /* + * The "template header" already includes the "v7tar" + * signature, various end-of-field markers and other required + * elements. + */ + memcpy(h, &template_header, 512); + + /* + * Because the block is already null-filled, and strings + * are allowed to exactly fill their destination (without null), + * I use memcpy(dest, src, strlen()) here a lot to copy strings. + */ + r = archive_entry_pathname_l(entry, &pp, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", + pp, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + if (strict && copy_length < V7TAR_name_size) + memcpy(h + V7TAR_name_offset, pp, copy_length); + else if (!strict && copy_length <= V7TAR_name_size) + memcpy(h + V7TAR_name_offset, pp, copy_length); + else { + /* Prefix is too long. */ + archive_set_error(&a->archive, ENAMETOOLONG, + "Pathname too long"); + ret = ARCHIVE_FAILED; + } + + r = archive_entry_hardlink_l(entry, &p, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", + p, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + if (copy_length > 0) + mytartype = '1'; + else { + r = archive_entry_symlink_l(entry, &p, ©_length, sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate linkname '%s' to %s", + p, archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + } + if (copy_length > 0) { + if (copy_length >= V7TAR_linkname_size) { + archive_set_error(&a->archive, ENAMETOOLONG, + "Link contents too long"); + ret = ARCHIVE_FAILED; + copy_length = V7TAR_linkname_size; + } + memcpy(h + V7TAR_linkname_offset, p, copy_length); + } + + if (format_number(archive_entry_mode(entry) & 07777, + h + V7TAR_mode_offset, V7TAR_mode_size, + V7TAR_mode_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Numeric mode too large"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_uid(entry), + h + V7TAR_uid_offset, V7TAR_uid_size, V7TAR_uid_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Numeric user ID too large"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_gid(entry), + h + V7TAR_gid_offset, V7TAR_gid_size, V7TAR_gid_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "Numeric group ID too large"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_size(entry), + h + V7TAR_size_offset, V7TAR_size_size, + V7TAR_size_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "File size out of range"); + ret = ARCHIVE_FAILED; + } + + if (format_number(archive_entry_mtime(entry), + h + V7TAR_mtime_offset, V7TAR_mtime_size, + V7TAR_mtime_max_size, strict)) { + archive_set_error(&a->archive, ERANGE, + "File modification time too large"); + ret = ARCHIVE_FAILED; + } + + if (mytartype >= 0) { + h[V7TAR_typeflag_offset] = mytartype; + } else { + switch (archive_entry_filetype(entry)) { + case AE_IFREG: case AE_IFDIR: + break; + case AE_IFLNK: + h[V7TAR_typeflag_offset] = '2'; + break; + case AE_IFCHR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "tar format cannot archive character device"); + return (ARCHIVE_FAILED); + case AE_IFBLK: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "tar format cannot archive block device"); + return (ARCHIVE_FAILED); + case AE_IFIFO: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "tar format cannot archive fifo"); + return (ARCHIVE_FAILED); + case AE_IFSOCK: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "tar format cannot archive socket"); + return (ARCHIVE_FAILED); + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "tar format cannot archive this (mode=0%lo)", + (unsigned long)archive_entry_mode(entry)); + ret = ARCHIVE_FAILED; + } + } + + checksum = 0; + for (i = 0; i < 512; i++) + checksum += 255 & (unsigned int)h[i]; + format_octal(checksum, h + V7TAR_checksum_offset, 6); + /* Can't be pre-set in the template. */ + h[V7TAR_checksum_offset + 6] = '\0'; + return (ret); +} + +/* + * Format a number into a field, with some intelligence. + */ +static int +format_number(int64_t v, char *p, int s, int maxsize, int strict) +{ + int64_t limit; + + limit = ((int64_t)1 << (s*3)); + + /* "Strict" only permits octal values with proper termination. */ + if (strict) + return (format_octal(v, p, s)); + + /* + * In non-strict mode, we allow the number to overwrite one or + * more bytes of the field termination. Even old tar + * implementations should be able to handle this with no + * problem. + */ + if (v >= 0) { + while (s <= maxsize) { + if (v < limit) + return (format_octal(v, p, s)); + s++; + limit <<= 3; + } + } + + /* Base-256 can handle any number, positive or negative. */ + return (format_256(v, p, maxsize)); +} + +/* + * Format a number into the specified field using base-256. + */ +static int +format_256(int64_t v, char *p, int s) +{ + p += s; + while (s-- > 0) { + *--p = (char)(v & 0xff); + v >>= 8; + } + *p |= 0x80; /* Set the base-256 marker bit. */ + return (0); +} + +/* + * Format a number into the specified field. + */ +static int +format_octal(int64_t v, char *p, int s) +{ + int len; + + len = s; + + /* Octal values can't be negative, so use 0. */ + if (v < 0) { + while (len-- > 0) + *p++ = '0'; + return (-1); + } + + p += s; /* Start at the end and work backwards. */ + while (s-- > 0) { + *--p = (char)('0' + (v & 7)); + v >>= 3; + } + + if (v == 0) + return (0); + + /* If it overflowed, fill field with max value. */ + while (len-- > 0) + *p++ = '7'; + + return (-1); +} + +static int +archive_write_v7tar_close(struct archive_write *a) +{ + return (__archive_write_nulls(a, 512*2)); +} + +static int +archive_write_v7tar_free(struct archive_write *a) +{ + struct v7tar *v7tar; + + v7tar = (struct v7tar *)a->format_data; + free(v7tar); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +static int +archive_write_v7tar_finish_entry(struct archive_write *a) +{ + struct v7tar *v7tar; + int ret; + + v7tar = (struct v7tar *)a->format_data; + ret = __archive_write_nulls(a, + (size_t)(v7tar->entry_bytes_remaining + v7tar->entry_padding)); + v7tar->entry_bytes_remaining = v7tar->entry_padding = 0; + return (ret); +} + +static ssize_t +archive_write_v7tar_data(struct archive_write *a, const void *buff, size_t s) +{ + struct v7tar *v7tar; + int ret; + + v7tar = (struct v7tar *)a->format_data; + if (s > v7tar->entry_bytes_remaining) + s = (size_t)v7tar->entry_bytes_remaining; + ret = __archive_write_output(a, buff, s); + v7tar->entry_bytes_remaining -= s; + if (ret != ARCHIVE_OK) + return (ret); + return (s); +} diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c index 96b7b2f92..a4ce7ee6f 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010-2011 Michihiro NAKAJIMA + * Copyright (c) 2010-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -97,6 +97,8 @@ archive_write_set_format_xar(struct archive *_a) /*#define DEBUG_PRINT_TOC 1 */ +#define BAD_CAST_CONST (const xmlChar *) + #define HEADER_MAGIC 0x78617221 #define HEADER_SIZE 28 #define HEADER_VERSION 1 @@ -414,7 +416,7 @@ xar_options(struct archive_write *a, const char *key, const char *value) else { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "Unkonwn checksum name: `%s'", + "Unknown checksum name: `%s'", value); return (ARCHIVE_FAILED); } @@ -448,7 +450,7 @@ xar_options(struct archive_write *a, const char *key, const char *value) else { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "Unkonwn compression name: `%s'", + "Unknown compression name: `%s'", value); return (ARCHIVE_FAILED); } @@ -468,7 +470,7 @@ xar_options(struct archive_write *a, const char *key, const char *value) value[1] != '\0') { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "Illeagal value `%s'", + "Illegal value `%s'", value); return (ARCHIVE_FAILED); } @@ -485,14 +487,17 @@ xar_options(struct archive_write *a, const char *key, const char *value) else { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, - "Unkonwn checksum name: `%s'", + "Unknown checksum name: `%s'", value); return (ARCHIVE_FAILED); } return (ARCHIVE_OK); } - return (ARCHIVE_FAILED); + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); } static int @@ -621,11 +626,11 @@ static int write_to_temp(struct archive_write *a, const void *buff, size_t s) { struct xar *xar; - unsigned char *p; + const unsigned char *p; ssize_t ws; xar = (struct xar *)a->format_data; - p = (unsigned char *)buff; + p = (const unsigned char *)buff; while (s) { ws = write(xar->temp_fd, p, s); if (ws < 0) { @@ -651,7 +656,7 @@ xar_write_data(struct archive_write *a, const void *buff, size_t s) xar = (struct xar *)a->format_data; if (s > xar->bytes_remaining) - s = xar->bytes_remaining; + s = (size_t)xar->bytes_remaining; if (s == 0 || xar->cur_file == NULL) return (0); if (xar->cur_file->data.compression == NONE) { @@ -676,7 +681,7 @@ xar_write_data(struct archive_write *a, const void *buff, size_t s) } #if !defined(_WIN32) || defined(__CYGWIN__) if (xar->bytes_remaining == - archive_entry_size(xar->cur_file->entry)) { + (uint64_t)archive_entry_size(xar->cur_file->entry)) { /* * Get the path of a shell script if so. */ @@ -732,7 +737,7 @@ xar_finish_entry(struct archive_write *a) return (ARCHIVE_OK); while (xar->bytes_remaining > 0) { - s = xar->bytes_remaining; + s = (size_t)xar->bytes_remaining; if (s > a->null_length) s = a->null_length; w = xar_write_data(a, a->nulls, s); @@ -756,7 +761,7 @@ xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer, { int r; - r = xmlTextWriterStartElement(writer, BAD_CAST(key)); + r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key)); if (r < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -765,7 +770,7 @@ xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer, } if (attrkey != NULL && attrvalue != NULL) { r = xmlTextWriterWriteAttribute(writer, - BAD_CAST(attrkey), BAD_CAST(attrvalue)); + BAD_CAST_CONST(attrkey), BAD_CAST_CONST(attrvalue)); if (r < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -774,7 +779,7 @@ xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer, } } if (value != NULL) { - r = xmlTextWriterWriteString(writer, BAD_CAST(value)); + r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value)); if (r < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -801,7 +806,7 @@ xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer, if (value == NULL) return (ARCHIVE_OK); - r = xmlTextWriterStartElement(writer, BAD_CAST(key)); + r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key)); if (r < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -809,7 +814,7 @@ xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer, return (ARCHIVE_FATAL); } if (value != NULL) { - r = xmlTextWriterWriteString(writer, BAD_CAST(value)); + r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value)); if (r < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -1062,7 +1067,7 @@ make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer, } while (p != NULL); if (n > 0) { - r = xmlTextWriterStartElement(writer, BAD_CAST(element)); + r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(element)); if (r < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -1557,7 +1562,7 @@ make_toc(struct archive_write *a) goto exit_toc; } r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"), - BAD_CAST(getalgname(xar->opt_toc_sumalg))); + BAD_CAST_CONST(getalgname(xar->opt_toc_sumalg))); if (r < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -1865,8 +1870,8 @@ static int file_cmp_node(const struct archive_rb_node *n1, const struct archive_rb_node *n2) { - struct file *f1 = (struct file *)n1; - struct file *f2 = (struct file *)n2; + const struct file *f1 = (const struct file *)n1; + const struct file *f2 = (const struct file *)n2; return (strcmp(f1->basename.s, f2->basename.s)); } @@ -1874,7 +1879,7 @@ file_cmp_node(const struct archive_rb_node *n1, static int file_cmp_key(const struct archive_rb_node *n, const void *key) { - struct file *f = (struct file *)n; + const struct file *f = (const struct file *)n; return (strcmp(f->basename.s, (const char *)key)); } @@ -1938,6 +1943,8 @@ file_create_virtual_dir(struct archive_write *a, struct xar *xar, { struct file *file; + (void)xar; /* UNUSED */ + file = file_new(a, NULL); if (file == NULL) return (NULL); @@ -2464,8 +2471,8 @@ static int file_hd_cmp_node(const struct archive_rb_node *n1, const struct archive_rb_node *n2) { - struct hardlink *h1 = (struct hardlink *)n1; - struct hardlink *h2 = (struct hardlink *)n2; + const struct hardlink *h1 = (const struct hardlink *)n1; + const struct hardlink *h2 = (const struct hardlink *)n2; return (strcmp(archive_entry_pathname(h1->file_list.first->entry), archive_entry_pathname(h2->file_list.first->entry))); @@ -2474,7 +2481,7 @@ file_hd_cmp_node(const struct archive_rb_node *n1, static int file_hd_cmp_key(const struct archive_rb_node *n, const void *key) { - struct hardlink *h = (struct hardlink *)n; + const struct hardlink *h = (const struct hardlink *)n; return (strcmp(archive_entry_pathname(h->file_list.first->entry), (const char *)key)); @@ -2589,10 +2596,10 @@ compression_init_encoder_gzip(struct archive *a, * a non-const pointer. */ strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; strm->avail_in = lastrm->avail_in; - strm->total_in = lastrm->total_in; + strm->total_in = (uLong)lastrm->total_in; strm->next_out = lastrm->next_out; strm->avail_out = lastrm->avail_out; - strm->total_out = lastrm->total_out; + strm->total_out = (uLong)lastrm->total_out; if (deflateInit2(strm, level, Z_DEFLATED, (withheader)?15:-15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { @@ -2622,10 +2629,10 @@ compression_code_gzip(struct archive *a, * a non-const pointer. */ strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; strm->avail_in = lastrm->avail_in; - strm->total_in = lastrm->total_in; + strm->total_in = (uLong)lastrm->total_in; strm->next_out = lastrm->next_out; strm->avail_out = lastrm->avail_out; - strm->total_out = lastrm->total_out; + strm->total_out = (uLong)lastrm->total_out; r = deflate(strm, (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH); lastrm->next_in = strm->next_in; @@ -2861,6 +2868,7 @@ compression_init_encoder_xz(struct archive *a, if (level > 6) level = 6; if (lzma_lzma_preset(&lzma_opt, level)) { + free(strm); lastrm->real_stream = NULL; archive_set_error(a, ENOMEM, "Internal error initializing compression library"); @@ -3082,8 +3090,10 @@ save_xattrs(struct archive_write *a, struct file *file) checksum_update(&(xar->a_sumwrk), value, size); checksum_final(&(xar->a_sumwrk), &(heap->a_sum)); if (write_to_temp(a, value, size) - != ARCHIVE_OK) + != ARCHIVE_OK) { + free(heap); return (ARCHIVE_FATAL); + } heap->length = size; /* Add heap to the tail of file->xattr. */ heap->next = NULL; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c index 11fbd45b5..5a9f114f0 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2008 Anselm Strauss * Copyright (c) 2009 Joerg Sonnenberger - * Copyright (c) 2011 Michihiro NAKAJIMA + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -109,69 +109,75 @@ static unsigned int dos_time(const time_t); static size_t path_length(struct archive_entry *); static int write_path(struct archive_entry *, struct archive_write *); -struct zip_local_file_header { - char signature[4]; - char version[2]; - char flags[2]; - char compression[2]; - char timedate[4]; - char crc32[4]; - char compressed_size[4]; - char uncompressed_size[4]; - char filename_length[2]; - char extra_length[2]; -}; - -struct zip_file_header { - char signature[4]; - char version_by[2]; - char version_extract[2]; - char flags[2]; - char compression[2]; - char timedate[4]; - char crc32[4]; - char compressed_size[4]; - char uncompressed_size[4]; - char filename_length[2]; - char extra_length[2]; - char comment_length[2]; - char disk_number[2]; - char attributes_internal[2]; - char attributes_external[4]; - char offset[4]; -}; - -struct zip_data_descriptor { - char signature[4]; /* Not mandatory, but recommended by specification. */ - char crc32[4]; - char compressed_size[4]; - char uncompressed_size[4]; -}; - -struct zip_extra_data_local { - char time_id[2]; - char time_size[2]; - char time_flag[1]; - char mtime[4]; - char atime[4]; - char ctime[4]; - char unix_id[2]; - char unix_size[2]; - char unix_version; - char unix_uid_size; - char unix_uid[4]; - char unix_gid_size; - char unix_gid[4]; -}; - -struct zip_extra_data_central { - char time_id[2]; - char time_size[2]; - char time_flag[1]; - char mtime[4]; - char unix_id[2]; - char unix_size[2]; -}; +#define LOCAL_FILE_HEADER_SIGNATURE 0 +#define LOCAL_FILE_HEADER_VERSION 4 +#define LOCAL_FILE_HEADER_FLAGS 6 +#define LOCAL_FILE_HEADER_COMPRESSION 8 +#define LOCAL_FILE_HEADER_TIMEDATE 10 +#define LOCAL_FILE_HEADER_CRC32 14 +#define LOCAL_FILE_HEADER_COMPRESSED_SIZE 18 +#define LOCAL_FILE_HEADER_UNCOMPRESSED_SIZE 22 +#define LOCAL_FILE_HEADER_FILENAME_LENGTH 26 +#define LOCAL_FILE_HEADER_EXTRA_LENGTH 28 +#define SIZE_LOCAL_FILE_HEADER 30 + +#define FILE_HEADER_SIGNATURE 0 +#define FILE_HEADER_VERSION_BY 4 +#define FILE_HEADER_VERSION_EXTRACT 6 +#define FILE_HEADER_FLAGS 8 +#define FILE_HEADER_COMPRESSION 10 +#define FILE_HEADER_TIMEDATE 12 +#define FILE_HEADER_CRC32 16 +#define FILE_HEADER_COMPRESSED_SIZE 20 +#define FILE_HEADER_UNCOMPRESSED_SIZE 24 +#define FILE_HEADER_FILENAME_LENGTH 28 +#define FILE_HEADER_EXTRA_LENGTH 30 +#define FILE_HEADER_COMMENT_LENGTH 32 +#define FILE_HEADER_DISK_NUMBER 34 +#define FILE_HEADER_ATTRIBUTES_INTERNAL 36 +#define FILE_HEADER_ATTRIBUTES_EXTERNAL 38 +#define FILE_HEADER_OFFSET 42 +#define SIZE_FILE_HEADER 46 + + /* Not mandatory, but recommended by specification. */ +#define DATA_DESCRIPTOR_SIGNATURE 0 +#define DATA_DESCRIPTOR_CRC32 4 +#define DATA_DESCRIPTOR_COMPRESSED_SIZE 8 +#define DATA_DESCRIPTOR_UNCOMPRESSED_SIZE 12 +#define SIZE_DATA_DESCRIPTOR 16 + +#define EXTRA_DATA_LOCAL_TIME_ID 0 +#define EXTRA_DATA_LOCAL_TIME_SIZE 2 +#define EXTRA_DATA_LOCAL_TIME_FLAG 4 +#define EXTRA_DATA_LOCAL_MTIME 5 +#define EXTRA_DATA_LOCAL_ATIME 9 +#define EXTRA_DATA_LOCAL_CTIME 13 +#define EXTRA_DATA_LOCAL_UNIX_ID 17 +#define EXTRA_DATA_LOCAL_UNIX_SIZE 19 +#define EXTRA_DATA_LOCAL_UNIX_VERSION 21 +#define EXTRA_DATA_LOCAL_UNIX_UID_SIZE 22 +#define EXTRA_DATA_LOCAL_UNIX_UID 23 +#define EXTRA_DATA_LOCAL_UNIX_GID_SIZE 27 +#define EXTRA_DATA_LOCAL_UNIX_GID 28 +#define SIZE_EXTRA_DATA_LOCAL 32 + +#define EXTRA_DATA_CENTRAL_TIME_ID 0 +#define EXTRA_DATA_CENTRAL_TIME_SIZE 2 +#define EXTRA_DATA_CENTRAL_TIME_FLAG 4 +#define EXTRA_DATA_CENTRAL_MTIME 5 +#define EXTRA_DATA_CENTRAL_UNIX_ID 9 +#define EXTRA_DATA_CENTRAL_UNIX_SIZE 11 +#define SIZE_EXTRA_DATA_CENTRAL 13 + +#define CENTRAL_DIRECTORY_END_SIGNATURE 0 +#define CENTRAL_DIRECTORY_END_DISK 4 +#define CENTRAL_DIRECTORY_END_START_DISK 6 +#define CENTRAL_DIRECTORY_END_ENTRIES_DISK 8 +#define CENTRAL_DIRECTORY_END_ENTRIES 10 +#define CENTRAL_DIRECTORY_END_SIZE 12 +#define CENTRAL_DIRECTORY_END_OFFSET 16 +#define CENTRAL_DIRECTORY_END_COMMENT_LENGTH 20 +#define SIZE_CENTRAL_DIRECTORY_END 22 struct zip_file_header_link { struct zip_file_header_link *next; @@ -184,7 +190,7 @@ struct zip_file_header_link { }; struct zip { - struct zip_data_descriptor data_descriptor; + uint8_t data_descriptor[SIZE_DATA_DESCRIPTOR]; struct zip_file_header_link *central_directory; struct zip_file_header_link *central_directory_end; int64_t offset; @@ -203,17 +209,6 @@ struct zip { #endif }; -struct zip_central_directory_end { - char signature[4]; - char disk[2]; - char start_disk[2]; - char entries_disk[2]; - char entries[2]; - char size[4]; - char offset[4]; - char comment_length[2]; -}; - static int archive_write_zip_options(struct archive_write *a, const char *key, const char *val) @@ -238,6 +233,7 @@ archive_write_zip_options(struct archive_write *a, const char *key, zip->compression = COMPRESSION_STORE; ret = ARCHIVE_OK; } + return (ret); } else if (strcmp(key, "hdrcharset") == 0) { if (val == NULL || val[0] == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -251,9 +247,61 @@ archive_write_zip_options(struct archive_write *a, const char *key, else ret = ARCHIVE_FATAL; } - } else + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +int +archive_write_zip_set_compression_deflate(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + int ret = ARCHIVE_FAILED; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER, + "archive_write_zip_set_compression_deflate"); + if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can only use archive_write_zip_set_compression_deflate" + " with zip format"); + ret = ARCHIVE_FATAL; + } else { +#ifdef HAVE_ZLIB_H + struct zip *zip = a->format_data; + zip->compression = COMPRESSION_DEFLATE; + ret = ARCHIVE_OK; +#else archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "%s: unknown keyword ``%s''", a->format_name, key); + "deflate compression not supported"); +#endif + } + return (ret); +} + +int +archive_write_zip_set_compression_store(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct zip *zip = a->format_data; + int ret = ARCHIVE_FAILED; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER, + "archive_write_zip_set_compression_deflate"); + if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can only use archive_write_zip_set_compression_store" + " with zip format"); + ret = ARCHIVE_FATAL; + } else { + zip->compression = COMPRESSION_STORE; + ret = ARCHIVE_OK; + } return (ret); } @@ -287,6 +335,7 @@ archive_write_set_format_zip(struct archive *_a) zip->len_buf = 65536; zip->buf = malloc(zip->len_buf); if (zip->buf == NULL) { + free(zip); archive_set_error(&a->archive, ENOMEM, "Can't allocate compression buffer"); return (ARCHIVE_FATAL); @@ -306,7 +355,7 @@ archive_write_set_format_zip(struct archive *_a) a->archive.archive_format = ARCHIVE_FORMAT_ZIP; a->archive.archive_format_name = "ZIP"; - archive_le32enc(&zip->data_descriptor.signature, + archive_le32enc(&zip->data_descriptor[DATA_DESCRIPTOR_SIGNATURE], ZIP_SIGNATURE_DATA_DESCRIPTOR); return (ARCHIVE_OK); @@ -328,9 +377,9 @@ static int archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) { struct zip *zip; - struct zip_local_file_header h; - struct zip_extra_data_local e; - struct zip_data_descriptor *d; + uint8_t h[SIZE_LOCAL_FILE_HEADER]; + uint8_t e[SIZE_EXTRA_DATA_LOCAL]; + uint8_t *d; struct zip_file_header_link *l; struct archive_string_conv *sconv; int ret, ret2 = ARCHIVE_OK; @@ -343,7 +392,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Filetype not supported"); return ARCHIVE_FAILED; - }; + }; /* Directory entries should have a size of 0. */ if (type == AE_IFDIR) @@ -370,7 +419,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) #endif } } - d = &zip->data_descriptor; + d = zip->data_descriptor; size = archive_entry_size(entry); zip->remaining_data_bytes = size; @@ -381,7 +430,21 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) "Can't allocate zip header data"); return (ARCHIVE_FATAL); } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + l->entry = __la_win_entry_in_posix_pathseparator(entry); + if (l->entry == entry) + l->entry = archive_entry_clone(entry); +#else l->entry = archive_entry_clone(entry); +#endif + if (l->entry == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip header data"); + free(l); + return (ARCHIVE_FATAL); + } l->flags = zip->flags; if (zip->opt_sconv != NULL) sconv = zip->opt_sconv; @@ -393,21 +456,47 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) if (archive_entry_pathname_l(entry, &p, &len, sconv) != 0) { if (errno == ENOMEM) { + archive_entry_free(l->entry); + free(l); archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathname"); return (ARCHIVE_FATAL); } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Can't translate pathname '%s' to %s", + "Can't translate Pathname '%s' to %s", archive_entry_pathname(entry), archive_string_conversion_charset_name(sconv)); ret2 = ARCHIVE_WARN; } if (len > 0) archive_entry_set_pathname(l->entry, p); + + /* + * Although there is no character-set regulation for Symlink, + * it is suitable to convert a character-set of Symlinke to + * what those of the Pathname has been converted to. + */ + if (type == AE_IFLNK) { + if (archive_entry_symlink_l(entry, &p, &len, sconv)) { + if (errno == ENOMEM) { + archive_entry_free(l->entry); + free(l); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory " + " for Symlink"); + return (ARCHIVE_FATAL); + } + /* + * Even if the strng conversion failed, + * we should not report the error since + * thre is no regulation for. + */ + } else if (len > 0) + archive_entry_set_symlink(l->entry, p); + } } - /* If all character of a filename is ASCII, Reset UTF-8 Name flag. */ + /* If all characters in a filename are ASCII, Reset UTF-8 Name flag. */ if ((l->flags & ZIP_FLAGS_UTF8_NAME) != 0 && is_all_ascii(archive_entry_pathname(l->entry))) l->flags &= ~ZIP_FLAGS_UTF8_NAME; @@ -440,13 +529,16 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) * directory. */ l->offset = zip->written_bytes; - memset(&h, 0, sizeof(h)); - archive_le32enc(&h.signature, ZIP_SIGNATURE_LOCAL_FILE_HEADER); - archive_le16enc(&h.version, ZIP_VERSION_EXTRACT); - archive_le16enc(&h.flags, l->flags); - archive_le16enc(&h.compression, l->compression); - archive_le32enc(&h.timedate, dos_time(archive_entry_mtime(entry))); - archive_le16enc(&h.filename_length, (uint16_t)path_length(l->entry)); + memset(h, 0, sizeof(h)); + archive_le32enc(&h[LOCAL_FILE_HEADER_SIGNATURE], + ZIP_SIGNATURE_LOCAL_FILE_HEADER); + archive_le16enc(&h[LOCAL_FILE_HEADER_VERSION], ZIP_VERSION_EXTRACT); + archive_le16enc(&h[LOCAL_FILE_HEADER_FLAGS], l->flags); + archive_le16enc(&h[LOCAL_FILE_HEADER_COMPRESSION], l->compression); + archive_le32enc(&h[LOCAL_FILE_HEADER_TIMEDATE], + dos_time(archive_entry_mtime(entry))); + archive_le16enc(&h[LOCAL_FILE_HEADER_FILENAME_LENGTH], + (uint16_t)path_length(l->entry)); switch (l->compression) { case COMPRESSION_STORE: @@ -454,18 +546,21 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) * specification says to set to zero when using data * descriptors. Otherwise the end of the data for an * entry is rather difficult to find. */ - archive_le32enc(&h.compressed_size, size); - archive_le32enc(&h.uncompressed_size, size); + archive_le32enc(&h[LOCAL_FILE_HEADER_COMPRESSED_SIZE], + (uint32_t)size); + archive_le32enc(&h[LOCAL_FILE_HEADER_UNCOMPRESSED_SIZE], + (uint32_t)size); break; #ifdef HAVE_ZLIB_H case COMPRESSION_DEFLATE: - archive_le32enc(&h.uncompressed_size, size); + archive_le32enc(&h[LOCAL_FILE_HEADER_UNCOMPRESSED_SIZE], + (uint32_t)size); zip->stream.zalloc = Z_NULL; zip->stream.zfree = Z_NULL; zip->stream.opaque = Z_NULL; zip->stream.next_out = zip->buf; - zip->stream.avail_out = zip->len_buf; + zip->stream.avail_out = (uInt)zip->len_buf; if (deflateInit2(&zip->stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { archive_set_error(&a->archive, ENOMEM, @@ -477,28 +572,33 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) } /* Formatting extra data. */ - archive_le16enc(&h.extra_length, sizeof(e)); - archive_le16enc(&e.time_id, ZIP_SIGNATURE_EXTRA_TIMESTAMP); - archive_le16enc(&e.time_size, sizeof(e.time_flag) + - sizeof(e.mtime) + sizeof(e.atime) + sizeof(e.ctime)); - e.time_flag[0] = 0x07; - archive_le32enc(&e.mtime, archive_entry_mtime(entry)); - archive_le32enc(&e.atime, archive_entry_atime(entry)); - archive_le32enc(&e.ctime, archive_entry_ctime(entry)); - - archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_NEW_UNIX); - archive_le16enc(&e.unix_size, sizeof(e.unix_version) + - sizeof(e.unix_uid_size) + sizeof(e.unix_uid) + - sizeof(e.unix_gid_size) + sizeof(e.unix_gid)); - e.unix_version = 1; - e.unix_uid_size = 4; - archive_le32enc(&e.unix_uid, archive_entry_uid(entry)); - e.unix_gid_size = 4; - archive_le32enc(&e.unix_gid, archive_entry_gid(entry)); - - archive_le32enc(&d->uncompressed_size, size); - - ret = __archive_write_output(a, &h, sizeof(h)); + archive_le16enc(&h[LOCAL_FILE_HEADER_EXTRA_LENGTH], sizeof(e)); + archive_le16enc(&e[EXTRA_DATA_LOCAL_TIME_ID], + ZIP_SIGNATURE_EXTRA_TIMESTAMP); + archive_le16enc(&e[EXTRA_DATA_LOCAL_TIME_SIZE], 1 + 4 * 3); + e[EXTRA_DATA_LOCAL_TIME_FLAG] = 0x07; + archive_le32enc(&e[EXTRA_DATA_LOCAL_MTIME], + (uint32_t)archive_entry_mtime(entry)); + archive_le32enc(&e[EXTRA_DATA_LOCAL_ATIME], + (uint32_t)archive_entry_atime(entry)); + archive_le32enc(&e[EXTRA_DATA_LOCAL_CTIME], + (uint32_t)archive_entry_ctime(entry)); + + archive_le16enc(&e[EXTRA_DATA_LOCAL_UNIX_ID], + ZIP_SIGNATURE_EXTRA_NEW_UNIX); + archive_le16enc(&e[EXTRA_DATA_LOCAL_UNIX_SIZE], 1 + (1 + 4) * 2); + e[EXTRA_DATA_LOCAL_UNIX_VERSION] = 1; + e[EXTRA_DATA_LOCAL_UNIX_UID_SIZE] = 4; + archive_le32enc(&e[EXTRA_DATA_LOCAL_UNIX_UID], + (uint32_t)archive_entry_uid(entry)); + e[EXTRA_DATA_LOCAL_UNIX_GID_SIZE] = 4; + archive_le32enc(&e[EXTRA_DATA_LOCAL_UNIX_GID], + (uint32_t)archive_entry_gid(entry)); + + archive_le32enc(&d[DATA_DESCRIPTOR_UNCOMPRESSED_SIZE], + (uint32_t)size); + + ret = __archive_write_output(a, h, sizeof(h)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(h); @@ -508,7 +608,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) return (ARCHIVE_FATAL); zip->written_bytes += ret; - ret = __archive_write_output(a, &e, sizeof(e)); + ret = __archive_write_output(a, e, sizeof(e)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(e); @@ -517,11 +617,11 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) const unsigned char *p; p = (const unsigned char *)archive_entry_symlink(l->entry); - ret = __archive_write_output(a, p, size); + ret = __archive_write_output(a, p, (size_t)size); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += size; - l->crc32 = crc32(l->crc32, p, size); + l->crc32 = crc32(l->crc32, p, (unsigned)size); } if (ret2 != ARCHIVE_OK) @@ -548,12 +648,12 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) zip->written_bytes += s; zip->remaining_data_bytes -= s; l->compressed_size += s; - l->crc32 = crc32(l->crc32, buff, s); + l->crc32 = crc32(l->crc32, buff, (unsigned)s); return (s); #if HAVE_ZLIB_H case COMPRESSION_DEFLATE: zip->stream.next_in = (unsigned char*)(uintptr_t)buff; - zip->stream.avail_in = s; + zip->stream.avail_in = (uInt)s; do { ret = deflate(&zip->stream, Z_NO_FLUSH); if (ret == Z_STREAM_ERROR) @@ -566,12 +666,12 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) l->compressed_size += zip->len_buf; zip->written_bytes += zip->len_buf; zip->stream.next_out = zip->buf; - zip->stream.avail_out = zip->len_buf; + zip->stream.avail_out = (uInt)zip->len_buf; } } while (zip->stream.avail_in != 0); zip->remaining_data_bytes -= s; /* If we have it, use zlib's fast crc32() */ - l->crc32 = crc32(l->crc32, buff, s); + l->crc32 = crc32(l->crc32, buff, (uInt)s); return (s); #endif @@ -588,7 +688,7 @@ archive_write_zip_finish_entry(struct archive_write *a) /* Write the data descripter after file data has been written. */ int ret; struct zip *zip = a->format_data; - struct zip_data_descriptor *d = &zip->data_descriptor; + uint8_t *d = zip->data_descriptor; struct zip_file_header_link *l = zip->central_directory_end; #if HAVE_ZLIB_H size_t reminder; @@ -612,19 +712,20 @@ archive_write_zip_finish_entry(struct archive_write *a) zip->stream.next_out = zip->buf; if (zip->stream.avail_out != 0) break; - zip->stream.avail_out = zip->len_buf; + zip->stream.avail_out = (uInt)zip->len_buf; } deflateEnd(&zip->stream); break; #endif } - archive_le32enc(&d->crc32, l->crc32); - archive_le32enc(&d->compressed_size, l->compressed_size); - ret = __archive_write_output(a, d, sizeof(*d)); + archive_le32enc(&d[DATA_DESCRIPTOR_CRC32], l->crc32); + archive_le32enc(&d[DATA_DESCRIPTOR_COMPRESSED_SIZE], + (uint32_t)l->compressed_size); + ret = __archive_write_output(a, d, SIZE_DATA_DESCRIPTOR); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); - zip->written_bytes += sizeof(*d); + zip->written_bytes += SIZE_DATA_DESCRIPTOR; return (ARCHIVE_OK); } @@ -633,9 +734,9 @@ archive_write_zip_close(struct archive_write *a) { struct zip *zip; struct zip_file_header_link *l; - struct zip_file_header h; - struct zip_central_directory_end end; - struct zip_extra_data_central e; + uint8_t h[SIZE_FILE_HEADER]; + uint8_t end[SIZE_CENTRAL_DIRECTORY_END]; + uint8_t e[SIZE_EXTRA_DATA_CENTRAL]; int64_t offset_start, offset_end; int entries; int ret; @@ -652,10 +753,10 @@ archive_write_zip_close(struct archive_write *a) * - disk_number * - attributes_internal */ - memset(&h, 0, sizeof(h)); - archive_le32enc(&h.signature, ZIP_SIGNATURE_FILE_HEADER); - archive_le16enc(&h.version_by, ZIP_VERSION_BY); - archive_le16enc(&h.version_extract, ZIP_VERSION_EXTRACT); + memset(h, 0, sizeof(h)); + archive_le32enc(&h[FILE_HEADER_SIGNATURE], ZIP_SIGNATURE_FILE_HEADER); + archive_le16enc(&h[FILE_HEADER_VERSION_BY], ZIP_VERSION_BY); + archive_le16enc(&h[FILE_HEADER_VERSION_EXTRACT], ZIP_VERSION_EXTRACT); entries = 0; offset_start = zip->written_bytes; @@ -663,31 +764,34 @@ archive_write_zip_close(struct archive_write *a) /* Formatting individual header fields per entry and * writing each entry. */ while (l != NULL) { - archive_le16enc(&h.flags, l->flags); - archive_le16enc(&h.compression, l->compression); - archive_le32enc(&h.timedate, + archive_le16enc(&h[FILE_HEADER_FLAGS], l->flags); + archive_le16enc(&h[FILE_HEADER_COMPRESSION], l->compression); + archive_le32enc(&h[FILE_HEADER_TIMEDATE], dos_time(archive_entry_mtime(l->entry))); - archive_le32enc(&h.crc32, l->crc32); - archive_le32enc(&h.compressed_size, l->compressed_size); - archive_le32enc(&h.uncompressed_size, - archive_entry_size(l->entry)); - archive_le16enc(&h.filename_length, + archive_le32enc(&h[FILE_HEADER_CRC32], l->crc32); + archive_le32enc(&h[FILE_HEADER_COMPRESSED_SIZE], + (uint32_t)l->compressed_size); + archive_le32enc(&h[FILE_HEADER_UNCOMPRESSED_SIZE], + (uint32_t)archive_entry_size(l->entry)); + archive_le16enc(&h[FILE_HEADER_FILENAME_LENGTH], (uint16_t)path_length(l->entry)); - archive_le16enc(&h.extra_length, sizeof(e)); - archive_le16enc(&h.attributes_external[2], + archive_le16enc(&h[FILE_HEADER_EXTRA_LENGTH], sizeof(e)); + archive_le16enc(&h[FILE_HEADER_ATTRIBUTES_EXTERNAL+2], archive_entry_mode(l->entry)); - archive_le32enc(&h.offset, l->offset); + archive_le32enc(&h[FILE_HEADER_OFFSET], (uint32_t)l->offset); /* Formatting extra data. */ - archive_le16enc(&e.time_id, ZIP_SIGNATURE_EXTRA_TIMESTAMP); - archive_le16enc(&e.time_size, - sizeof(e.mtime) + sizeof(e.time_flag)); - e.time_flag[0] = 0x07; - archive_le32enc(&e.mtime, archive_entry_mtime(l->entry)); - archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_NEW_UNIX); - archive_le16enc(&e.unix_size, 0x0000); - - ret = __archive_write_output(a, &h, sizeof(h)); + archive_le16enc(&e[EXTRA_DATA_CENTRAL_TIME_ID], + ZIP_SIGNATURE_EXTRA_TIMESTAMP); + archive_le16enc(&e[EXTRA_DATA_CENTRAL_TIME_SIZE], 1 + 4); + e[EXTRA_DATA_CENTRAL_TIME_FLAG] = 0x07; + archive_le32enc(&e[EXTRA_DATA_CENTRAL_MTIME], + (uint32_t)archive_entry_mtime(l->entry)); + archive_le16enc(&e[EXTRA_DATA_CENTRAL_UNIX_ID], + ZIP_SIGNATURE_EXTRA_NEW_UNIX); + archive_le16enc(&e[EXTRA_DATA_CENTRAL_UNIX_SIZE], 0x0000); + + ret = __archive_write_output(a, h, sizeof(h)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(h); @@ -697,7 +801,7 @@ archive_write_zip_close(struct archive_write *a) return (ARCHIVE_FATAL); zip->written_bytes += ret; - ret = __archive_write_output(a, &e, sizeof(e)); + ret = __archive_write_output(a, e, sizeof(e)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(e); @@ -708,15 +812,18 @@ archive_write_zip_close(struct archive_write *a) offset_end = zip->written_bytes; /* Formatting end of central directory. */ - memset(&end, 0, sizeof(end)); - archive_le32enc(&end.signature, ZIP_SIGNATURE_CENTRAL_DIRECTORY_END); - archive_le16enc(&end.entries_disk, entries); - archive_le16enc(&end.entries, entries); - archive_le32enc(&end.size, offset_end - offset_start); - archive_le32enc(&end.offset, offset_start); + memset(end, 0, sizeof(end)); + archive_le32enc(&end[CENTRAL_DIRECTORY_END_SIGNATURE], + ZIP_SIGNATURE_CENTRAL_DIRECTORY_END); + archive_le16enc(&end[CENTRAL_DIRECTORY_END_ENTRIES_DISK], entries); + archive_le16enc(&end[CENTRAL_DIRECTORY_END_ENTRIES], entries); + archive_le32enc(&end[CENTRAL_DIRECTORY_END_SIZE], + (uint32_t)(offset_end - offset_start)); + archive_le32enc(&end[CENTRAL_DIRECTORY_END_OFFSET], + (uint32_t)offset_start); /* Writing end of central directory. */ - ret = __archive_write_output(a, &end, sizeof(end)); + ret = __archive_write_output(a, end, sizeof(end)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(end); @@ -784,7 +891,10 @@ path_length(struct archive_entry *entry) type = archive_entry_filetype(entry); path = archive_entry_pathname(entry); - if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) { + if (path == NULL) + return (0); + if (type == AE_IFDIR && + (path[0] == '\0' || path[strlen(path) - 1] != '/')) { return strlen(path) + 1; } else { return strlen(path); diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_options.3 b/Utilities/cmlibarchive/libarchive/archive_write_set_options.3 index 9a8ea3dbf..9d605151a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_options.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_options.3 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $ +.\" $FreeBSD$ .\" -.Dd Feb 27, 2010 +.Dd February 2, 2012 .Dt ARCHIVE_WRITE_OPTIONS 3 .Os .Sh NAME @@ -33,8 +33,8 @@ .Nm archive_write_set_option , .Nm archive_write_set_options .Nd functions controlling options for reading archives -.Sh SYNOPSIS -.\" +.Sh LIBRARY +Streaming Archive Library (libarchive, -larchive) .Sh SYNOPSIS .Ft int .Fo archive_write_set_filter_option diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_options.c b/Utilities/cmlibarchive/libarchive/archive_write_set_options.c index a8c2d23dd..962309ada 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_options.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_options.c @@ -78,11 +78,13 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o, struct archive_write *a = (struct archive_write *)_a; if (a->format_name == NULL) - return (ARCHIVE_FAILED); + return (m == NULL)?ARCHIVE_FAILED:ARCHIVE_WARN - 1; + /* If the format name didn't match, return a special code for + * _archive_set_option[s]. */ if (m != NULL && strcmp(m, a->format_name) != 0) - return (ARCHIVE_FAILED); + return (ARCHIVE_WARN - 1); if (a->format_options == NULL) - return (ARCHIVE_FAILED); + return (ARCHIVE_WARN); return a->format_options(a, o, v); } @@ -92,7 +94,7 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o, { struct archive_write *a = (struct archive_write *)_a; struct archive_write_filter *filter; - int r, rv = ARCHIVE_FAILED; + int r, rv = ARCHIVE_WARN; for (filter = a->filter_first; filter != NULL; filter = filter->next_filter) { if (filter->options == NULL) @@ -111,6 +113,10 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o, if (r == ARCHIVE_OK) rv = ARCHIVE_OK; } + /* If the filter name didn't match, return a special code for + * _archive_set_option[s]. */ + if (rv == ARCHIVE_WARN && m != NULL) + rv = ARCHIVE_WARN - 1; return (rv); } diff --git a/Utilities/cmlibarchive/libarchive/cpio.5 b/Utilities/cmlibarchive/libarchive/cpio.5 index 13a4445b7..1a2886f08 100644 --- a/Utilities/cmlibarchive/libarchive/cpio.5 +++ b/Utilities/cmlibarchive/libarchive/cpio.5 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/cpio.5,v 1.2 2008/05/26 17:00:23 kientzle Exp $ +.\" $FreeBSD$ .\" -.Dd October 5, 2007 +.Dd December 23, 2011 .Dt CPIO 5 .Os .Sh NAME diff --git a/Utilities/cmlibarchive/libarchive/filter_fork.h b/Utilities/cmlibarchive/libarchive/filter_fork.h index 453d032d1..a28272bee 100644 --- a/Utilities/cmlibarchive/libarchive/filter_fork.h +++ b/Utilities/cmlibarchive/libarchive/filter_fork.h @@ -33,7 +33,7 @@ #define FILTER_FORK_H pid_t -__archive_create_child(const char *path, int *child_stdin, int *child_stdout); +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout); void __archive_check_child(int in, int out); diff --git a/Utilities/cmlibarchive/libarchive/filter_fork.c b/Utilities/cmlibarchive/libarchive/filter_fork_posix.c index d160524b0..02dbd4bb4 100644 --- a/Utilities/cmlibarchive/libarchive/filter_fork.c +++ b/Utilities/cmlibarchive/libarchive/filter_fork_posix.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2007 Joerg Sonnenberger + * Copyright (c) 2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,10 +28,19 @@ /* This capability is only available on POSIX systems. */ #if defined(HAVE_PIPE) && defined(HAVE_FCNTL) && \ - (defined(HAVE_FORK) || defined(HAVE_VFORK)) + (defined(HAVE_FORK) || defined(HAVE_VFORK) || defined(HAVE_POSIX_SPAWNP)) __FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00Z kientzle $"); +#if defined(HAVE_SYS_TYPES_H) +# include <sys/types.h> +#endif +#ifdef HAVE_ERRNO_H +# include <errno.h> +#endif +#ifdef HAVE_STRING_H +# include <string.h> +#endif #if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)) # if defined(HAVE_POLL_H) # include <poll.h> @@ -47,17 +57,37 @@ __FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00 #ifdef HAVE_FCNTL_H # include <fcntl.h> #endif +#ifdef HAVE_SPAWN_H +# include <spawn.h> +#endif +#ifdef HAVE_STDLIB_H +# include <stdlib.h> +#endif #ifdef HAVE_UNISTD_H # include <unistd.h> #endif +#include "archive.h" +#include "archive_cmdline_private.h" + #include "filter_fork.h" pid_t -__archive_create_child(const char *path, int *child_stdin, int *child_stdout) +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) { pid_t child; int stdin_pipe[2], stdout_pipe[2], tmp; +#if HAVE_POSIX_SPAWNP + posix_spawn_file_actions_t actions; + int r; +#endif + struct archive_cmdline *cmdline; + + cmdline = __archive_cmdline_allocate(); + if (cmdline == NULL) + goto state_allocated; + if (__archive_cmdline_parse(cmdline, cmd) != ARCHIVE_OK) + goto state_allocated; if (pipe(stdin_pipe) == -1) goto state_allocated; @@ -76,14 +106,53 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout) stdout_pipe[1] = tmp; } +#if HAVE_POSIX_SPAWNP + + r = posix_spawn_file_actions_init(&actions); + if (r != 0) { + errno = r; + goto stdout_opened; + } + r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[1]); + if (r != 0) + goto actions_inited; + r = posix_spawn_file_actions_addclose(&actions, stdout_pipe[0]); + if (r != 0) + goto actions_inited; + /* Setup for stdin. */ + r = posix_spawn_file_actions_adddup2(&actions, stdin_pipe[0], 0); + if (r != 0) + goto actions_inited; + if (stdin_pipe[0] != 0 /* stdin */) { + r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[0]); + if (r != 0) + goto actions_inited; + } + /* Setup for stdout. */ + r = posix_spawn_file_actions_adddup2(&actions, stdout_pipe[1], 1); + if (r != 0) + goto actions_inited; + if (stdout_pipe[1] != 1 /* stdout */) { + r = posix_spawn_file_actions_addclose(&actions, stdout_pipe[1]); + if (r != 0) + goto actions_inited; + } + r = posix_spawnp(&child, cmdline->path, &actions, NULL, + cmdline->argv, NULL); + if (r != 0) + goto actions_inited; + posix_spawn_file_actions_destroy(&actions); + +#else /* HAVE_POSIX_SPAWNP */ + #if HAVE_VFORK - switch ((child = vfork())) { + child = vfork(); #else - switch ((child = fork())) { + child = fork(); #endif - case -1: + if (child == -1) goto stdout_opened; - case 0: + if (child == 0) { close(stdin_pipe[1]); close(stdout_pipe[0]); if (dup2(stdin_pipe[0], 0 /* stdin */) == -1) @@ -94,20 +163,27 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout) _exit(254); if (stdout_pipe[1] != 1 /* stdout */) close(stdout_pipe[1]); - execlp(path, path, (char *)NULL); + execvp(cmdline->path, cmdline->argv); _exit(254); - default: - close(stdin_pipe[0]); - close(stdout_pipe[1]); - - *child_stdin = stdin_pipe[1]; - fcntl(*child_stdin, F_SETFL, O_NONBLOCK); - *child_stdout = stdout_pipe[0]; - fcntl(*child_stdout, F_SETFL, O_NONBLOCK); } +#endif /* HAVE_POSIX_SPAWNP */ + + close(stdin_pipe[0]); + close(stdout_pipe[1]); + + *child_stdin = stdin_pipe[1]; + fcntl(*child_stdin, F_SETFL, O_NONBLOCK); + *child_stdout = stdout_pipe[0]; + fcntl(*child_stdout, F_SETFL, O_NONBLOCK); + __archive_cmdline_free(cmdline); return child; +#if HAVE_POSIX_SPAWNP +actions_inited: + errno = r; + posix_spawn_file_actions_destroy(&actions); +#endif stdout_opened: close(stdout_pipe[0]); close(stdout_pipe[1]); @@ -115,6 +191,7 @@ stdin_opened: close(stdin_pipe[0]); close(stdin_pipe[1]); state_allocated: + __archive_cmdline_free(cmdline); return -1; } diff --git a/Utilities/cmlibarchive/libarchive/filter_fork_windows.c b/Utilities/cmlibarchive/libarchive/filter_fork_windows.c index 272e56c6b..fa59cc9e9 100644 --- a/Utilities/cmlibarchive/libarchive/filter_fork_windows.c +++ b/Utilities/cmlibarchive/libarchive/filter_fork_windows.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009 Michihiro NAKAJIMA + * Copyright (c) 2009-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,17 +26,100 @@ #include "archive_platform.h" #if defined(_WIN32) && !defined(__CYGWIN__) +#include "archive_cmdline_private.h" +#include "archive_string.h" #include "filter_fork.h" pid_t -__archive_create_child(const char *path, int *child_stdin, int *child_stdout) +__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout) { HANDLE childStdout[2], childStdin[2],childStderr; SECURITY_ATTRIBUTES secAtts; STARTUPINFO staInfo; PROCESS_INFORMATION childInfo; - char cmd[MAX_PATH]; + struct archive_string cmdline; + struct archive_string fullpath; + struct archive_cmdline *acmd; + char *arg0, *ext; + int i, l; + DWORD fl, fl_old; + + childStdout[0] = childStdout[1] = INVALID_HANDLE_VALUE; + childStdin[0] = childStdin[1] = INVALID_HANDLE_VALUE; + childStderr = INVALID_HANDLE_VALUE; + archive_string_init(&cmdline); + archive_string_init(&fullpath); + + acmd = __archive_cmdline_allocate(); + if (acmd == NULL) + goto fail; + if (__archive_cmdline_parse(acmd, cmd) != ARCHIVE_OK) + goto fail; + + /* + * Search the full path of 'path'. + * NOTE: This does not need if we give CreateProcessA 'path' as + * a part of the cmdline and give CreateProcessA NULL as first + * parameter, but I do not like that way. + */ + ext = strrchr(acmd->path, '.'); + if (ext == NULL || strlen(ext) > 4) + /* 'path' does not have a proper extension, so we have to + * give SearchPath() ".exe" as the extension. */ + ext = ".exe"; + else + ext = NULL;/* 'path' has an extension. */ + + fl = MAX_PATH; + do { + if (archive_string_ensure(&fullpath, fl) == NULL) + goto fail; + fl_old = fl; + fl = SearchPathA(NULL, acmd->path, ext, fl, fullpath.s, + &arg0); + } while (fl != 0 && fl > fl_old); + if (fl == 0) + goto fail; + + /* + * Make a command line. + */ + for (l = 0, i = 0; acmd->argv[i] != NULL; i++) { + if (i == 0) + continue; + l += (int)strlen(acmd->argv[i]) + 1; + } + if (archive_string_ensure(&cmdline, l + 1) == NULL) + goto fail; + for (i = 0; acmd->argv[i] != NULL; i++) { + if (i == 0) { + const char *p, *sp; + + if ((p = strchr(acmd->argv[i], '/')) != NULL || + (p = strchr(acmd->argv[i], '\\')) != NULL) + p++; + else + p = acmd->argv[i]; + if ((sp = strchr(p, ' ')) != NULL) + archive_strappend_char(&cmdline, '"'); + archive_strcat(&cmdline, p); + if (sp != NULL) + archive_strappend_char(&cmdline, '"'); + } else { + archive_strappend_char(&cmdline, ' '); + archive_strcat(&cmdline, acmd->argv[i]); + } + } + if (i <= 1) { + const char *sp; + + if ((sp = strchr(arg0, ' ')) != NULL) + archive_strappend_char(&cmdline, '"'); + archive_strcat(&cmdline, arg0); + if (sp != NULL) + archive_strappend_char(&cmdline, '"'); + } secAtts.nLength = sizeof(SECURITY_ATTRIBUTES); secAtts.bInheritHandle = TRUE; @@ -44,33 +127,15 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout) if (CreatePipe(&childStdout[0], &childStdout[1], &secAtts, 0) == 0) goto fail; if (!SetHandleInformation(childStdout[0], HANDLE_FLAG_INHERIT, 0)) - { - CloseHandle(childStdout[0]); - CloseHandle(childStdout[1]); goto fail; - } - if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0) { - CloseHandle(childStdout[0]); - CloseHandle(childStdout[1]); + if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0) goto fail; - } if (!SetHandleInformation(childStdin[1], HANDLE_FLAG_INHERIT, 0)) - { - CloseHandle(childStdout[0]); - CloseHandle(childStdout[1]); - CloseHandle(childStdin[0]); - CloseHandle(childStdin[1]); goto fail; - } if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), GetCurrentProcess(), &childStderr, 0, TRUE, - DUPLICATE_SAME_ACCESS) == 0) { - CloseHandle(childStdout[0]); - CloseHandle(childStdout[1]); - CloseHandle(childStdin[0]); - CloseHandle(childStdin[1]); + DUPLICATE_SAME_ACCESS) == 0) goto fail; - } memset(&staInfo, 0, sizeof(staInfo)); staInfo.cb = sizeof(staInfo); @@ -79,17 +144,9 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout) staInfo.hStdInput = childStdin[0]; staInfo.wShowWindow = SW_HIDE; staInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - strncpy(cmd, path, sizeof(cmd)-1); - cmd[sizeof(cmd)-1] = '\0'; - if (CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, - &staInfo, &childInfo) == 0) { - CloseHandle(childStdout[0]); - CloseHandle(childStdout[1]); - CloseHandle(childStdin[0]); - CloseHandle(childStdin[1]); - CloseHandle(childStderr); + if (CreateProcessA(fullpath.s, cmdline.s, NULL, NULL, TRUE, 0, + NULL, NULL, &staInfo, &childInfo) == 0) goto fail; - } WaitForInputIdle(childInfo.hProcess, INFINITE); CloseHandle(childInfo.hProcess); CloseHandle(childInfo.hThread); @@ -100,17 +157,33 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout) CloseHandle(childStdout[1]); CloseHandle(childStdin[0]); + archive_string_free(&cmdline); + archive_string_free(&fullpath); + __archive_cmdline_free(acmd); return (childInfo.dwProcessId); fail: + if (childStdout[0] != INVALID_HANDLE_VALUE) + CloseHandle(childStdout[0]); + if (childStdout[1] != INVALID_HANDLE_VALUE) + CloseHandle(childStdout[1]); + if (childStdin[0] != INVALID_HANDLE_VALUE) + CloseHandle(childStdin[0]); + if (childStdin[1] != INVALID_HANDLE_VALUE) + CloseHandle(childStdin[1]); + if (childStderr != INVALID_HANDLE_VALUE) + CloseHandle(childStderr); + archive_string_free(&cmdline); + archive_string_free(&fullpath); + __archive_cmdline_free(acmd); return (-1); } void __archive_check_child(int in, int out) { - (void)in; /* UNSED */ - (void)out; /* UNSED */ + (void)in; /* UNUSED */ + (void)out; /* UNUSED */ Sleep(100); } diff --git a/Utilities/cmlibarchive/libarchive/libarchive-formats.5 b/Utilities/cmlibarchive/libarchive/libarchive-formats.5 index d223bf853..4a709b33c 100644 --- a/Utilities/cmlibarchive/libarchive/libarchive-formats.5 +++ b/Utilities/cmlibarchive/libarchive/libarchive-formats.5 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/libarchive-formats.5 201077 2009-12-28 01:50:23Z kientzle $ +.\" $FreeBSD$ .\" -.Dd December 27, 2009 +.Dd March 18, 2012 .Dt LIBARCHIVE-FORMATS 5 .Os .Sh NAME @@ -51,11 +51,11 @@ functions to enable all supported formats. The .Xr libarchive 3 library can read most tar archives. -However, it only writes POSIX-standard +It can write POSIX-standard .Dq ustar and .Dq pax interchange -formats. +formats and a subset of the legacy GNU tar format. .Pp All tar formats store each entry in one or more 512-byte records. The first record is used for file metadata, including filename, @@ -70,13 +70,18 @@ subsequent entries. .It Cm gnutar The .Xr libarchive 3 -library can read GNU-format tar archives. +library can read most GNU-format tar archives. It currently supports the most popular GNU extensions, including modern long filename and linkname support, as well as atime and ctime data. The libarchive library does not support multi-volume archives, nor the old GNU long filename format. It can read GNU sparse file entries, including the new POSIX-based -formats, but cannot write GNU sparse file entries. +formats. +.Pp +The +.Xr libarchive 3 +library can write GNU tar format, including long filename +and linkname support, as well as atime and ctime data. .It Cm pax The .Xr libarchive 3 @@ -98,6 +103,14 @@ archiver and a few LIBARCHIVE keys. The libarchive library can read most of the SCHILY keys and most of the GNU keys introduced by GNU tar. It silently ignores any keywords that it does not understand. +.Pp +The pax interchange format converts filenames to Unicode +and stores them using the UTF-8 encoding. +Prior to libarchive 3.0, libarchive erroneously assumed +that the system wide-character routines natively supported +Unicode. +This caused it to mis-handle non-ASCII filenames on systems +that did not satisfy this assumption. .It Cm restricted pax The libarchive library can also write pax archives in which it attempts to suppress the extended attributes entry whenever @@ -135,6 +148,8 @@ security information cannot be stored. Archive entries are limited to 8 gigabytes in size. .El Note that the pax interchange format has none of these restrictions. +The ustar format is old and widely supported. +It is recommended when compatibility is the primary concern. .El .Pp The libarchive library also reads a variety of commonly-used extensions to @@ -268,19 +283,68 @@ If both extensions are present, the Joliet extensions will be used and the Rockridge extensions will be ignored. In particular, this can create problems with hardlinks and symlinks, which are supported by Rockridge but not by Joliet. +.Pp +Libarchive reads ISO9660 images using a streaming strategy. +This allows it to read compressed images directly +(decompressing on the fly) and allows it to read images +directly from network sockets, pipes, and other non-seekable +data sources. +This strategy works well for optimized ISO9660 images created +by many popular programs. +Such programs collect all directory information at the beginning +of the ISO9660 image so it can be read from a physical disk +with a minimum of seeking. +However, not all ISO9660 images can be read in this fashion. +.Pp +Libarchive can also write ISO9660 images. +Such images are fully optimized with the directory information +preceding all file data. +This is done by storing all file data to a temporary file +while collecting directory information in memory. +When the image is finished, libarchive writes out the +directory structure followed by the file data. +The location used for the temporary file can be changed +by the usual environment variables. .Ss Zip format Libarchive can read and write zip format archives that have uncompressed entries and entries compressed with the .Dq deflate algorithm. -Older zip compression algorithms are not supported. -It can extract jar archives, archives that use Zip64 extensions and many +Other zip compression algorithms are not supported. +It can extract jar archives, archives that use Zip64 extensions and self-extracting zip archives. -Libarchive reads Zip archives as they are being streamed, -which allows it to read archives of arbitrary size. -It currently does not use the central directory; this -limits libarchive's ability to support some self-extracting -archives and ones that have been modified in certain ways. +Libarchive can use either of two different strategies for +reading Zip archives: +a streaming strategy which is fast and can handle extremely +large archives, and a seeking strategy which can correctly +process self-extracting Zip archives and archives with +deleted members or other in-place modifications. +.Pp +The streaming reader processes Zip archives as they are read. +It can read archives of arbitrary size from tape or +network sockets, and can decode Zip archives that have +been separately compressed or encoded. +However, self-extracting Zip archives and archives with +certain types of modifications cannot be correctly +handled. +Such archives require that the reader first process the +Central Directory, which is ordinarily located +at the end of a Zip archive and is thus inaccessible +to the streaming reader. +If the program using libarchive has enabled seek support, then +libarchive will use this to processes the central directory first. +.Pp +In particular, the seeking reader must be used to +correctly handle self-extracting archives. +Such archives consist of a program followed by a regular +Zip archive. +The streaming reader cannot parse the initial program +portion, but the seeking reader starts by reading the +Central Directory from the end of the archive. +Similarly, Zip archives that have been modified in-place +can have deleted entries or other garbage data that +can only be accurately detected by first reading the +Central Directory. .Ss Archive (library) file format The Unix archive format (commonly created by the .Xr ar 1 @@ -315,7 +379,7 @@ of a file hierarchy in which each line specifies the name of a file and provides specific metadata about that file. Libarchive can read all of the keywords supported by both the NetBSD and FreeBSD versions of -.Xr mtree 1 , +.Xr mtree 8 , although many of the keywords cannot currently be stored in an .Tn archive_entry object. @@ -342,12 +406,18 @@ using libarchive. If it cannot locate and open the file on disk, libarchive will return an error for any attempt to read the entry body. +.Ss LHA +XXX Information about libarchive's LHA support XXX +.Ss CAB +XXX Information about libarchive's CAB support XXX +.Ss XAR +XXX Information about libarchive's XAR support XXX .Ss RAR -libarchive has limited support to read files in RAR format. Currently, -libarchive can read single RAR files in RARv3 format which have been either -created uncompressed, or compressed using any of the compression methods -supported by the RARv3 format. libarchive can also extract RAR files which have -been created as self-extracting RAR files. +Libarchive has limited support for reading RAR format archives. +Currently, libarchive can read RARv3 format archives +which have been either created uncompressed, or compressed using +any of the compression methods supported by the RARv3 format. +Libarchive can also read self-extracting RAR archives. .Sh SEE ALSO .Xr ar 1 , .Xr cpio 1 , diff --git a/Utilities/cmlibarchive/libarchive/libarchive.3 b/Utilities/cmlibarchive/libarchive/libarchive.3 index d655404b8..3a9a841d3 100644 --- a/Utilities/cmlibarchive/libarchive/libarchive.3 +++ b/Utilities/cmlibarchive/libarchive/libarchive.3 @@ -22,16 +22,14 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/libarchive.3,v 1.11 2007/01/09 08:05:56 kientzle Exp $ +.\" $FreeBSD$ .\" -.Dd February 6, 2010 +.Dd March 18, 2012 .Dt LIBARCHIVE 3 .Os .Sh NAME .Nm libarchive .Nd functions for reading and writing streaming archives -.Sh LIBRARY -.Lb libarchive .Sh OVERVIEW The .Nm @@ -66,15 +64,33 @@ most common cpio archive formats, .It ISO9660 CD images (including RockRidge and Joliet extensions), .It -Zip archives. +Zip archives, +.It +ar archives (including GNU/SysV and BSD extensions), +.It +Microsoft CAB archives, +.It +LHA archives, +.It +mtree file tree descriptions, +.It +RAR archives, +.It +XAR archives. .El The library automatically detects archives compressed with .Xr gzip 1 , .Xr bzip2 1 , .Xr xz 1 , +.Xr lzip 1 , or .Xr compress 1 and decompresses them transparently. +It can similarly detect and decode archives processed with +.Xr uuencode 1 +or which have an +.Xr rpm 1 +header. .Pp When writing an archive, you can specify the compression to be used and the format to use. @@ -93,7 +109,17 @@ POSIX octet-oriented cpio archives, .It Zip archive, .It -two different variants of shar archives. +two different variants of shar archives, +.It +ISO9660 CD images, +.It +7-Zip archives, +.It +ar archives, +.It +mtree file tree descriptions, +.It +XAR archives. .El Pax interchange format is an extension of the tar archive format that eliminates essentially all of the limitations of historic tar formats @@ -145,9 +171,21 @@ operations. .Sh READING ENTRIES FROM DISK The .Xr archive_read_disk 3 -provides some support for populating +supports for populating .Xr archive_entry 3 objects from information in the filesystem. +This includes the information accessible from the +.Xr stat 2 +system call as well as ACLs, extended attributes, +and other metadata. +The +.Xr archive_read_disk 3 +API also supports iterating over directory trees, +which allows directories of files to be read using +an API compatible with +the +.Xr archive_read 3 +API. .Sh DESCRIPTION Detailed descriptions of each function are provided by the corresponding manual pages. @@ -227,7 +265,7 @@ library first appeared in .An -nosplit The .Nm libarchive -library was written by +library was originally written by .An Tim Kientzle Aq kientzle@acm.org . .Sh BUGS Some archive formats support information that is not supported by @@ -244,13 +282,8 @@ is supported by all formats. For example, cpio formats do not support nanosecond timestamps; old tar formats do not support large device numbers. .Pp -The -.Xr archive_read_disk 3 -API should support iterating over filesystems; -that would make it possible to share code among -disk-to-archive, archive-to-archive, archive-to-disk, -and disk-to-disk operations. -Currently, it only supports reading the -information for a single file. -(Which is still quite useful, as it hides a lot -of system-specific details.) +The ISO9660 reader cannot yet read all ISO9660 images; +it should learn how to seek. +.Pp +The AR writer requires the client program to use +two passes, unlike all other libarchive writers. diff --git a/Utilities/cmlibarchive/libarchive/libarchive_changes.3 b/Utilities/cmlibarchive/libarchive/libarchive_changes.3 index 6ee6af245..bacd6e123 100644 --- a/Utilities/cmlibarchive/libarchive/libarchive_changes.3 +++ b/Utilities/cmlibarchive/libarchive/libarchive_changes.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 27, 2011 +.Dd December 23, 2011 .Dt LIBARCHIVE_CHANGES 3 .Os .Sh NAME diff --git a/Utilities/cmlibarchive/libarchive/libarchive_internals.3 b/Utilities/cmlibarchive/libarchive/libarchive_internals.3 index 776f4c351..4aa09f93e 100644 --- a/Utilities/cmlibarchive/libarchive/libarchive_internals.3 +++ b/Utilities/cmlibarchive/libarchive/libarchive_internals.3 @@ -22,10 +22,10 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/lib/libarchive/libarchive_internals.3,v 1.2 2007/12/30 04:58:22 kientzle Exp $ +.\" $FreeBSD$ .\" -.Dd April 16, 2007 -.Dt LIBARCHIVE 3 +.Dd January 26, 2011 +.Dt LIBARCHIVE_INTERNALS 3 .Os .Sh NAME .Nm libarchive_internals diff --git a/Utilities/cmlibarchive/libarchive/mtree.5 b/Utilities/cmlibarchive/libarchive/mtree.5 index b6637d6f5..983fff723 100644 --- a/Utilities/cmlibarchive/libarchive/mtree.5 +++ b/Utilities/cmlibarchive/libarchive/mtree.5 @@ -28,7 +28,7 @@ .\" From: @(#)mtree.8 8.2 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" -.Dd August 20, 2007 +.Dd May 6, 2008 .Dt MTREE 5 .Os .Sh NAME diff --git a/Utilities/cmlibarchive/libarchive/tar.5 b/Utilities/cmlibarchive/libarchive/tar.5 index 65875bd61..688bb922c 100644 --- a/Utilities/cmlibarchive/libarchive/tar.5 +++ b/Utilities/cmlibarchive/libarchive/tar.5 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: head/lib/libarchive/tar.5 201077 2009-12-28 01:50:23Z kientzle $ +.\" $FreeBSD$ .\" -.Dd December 27, 2009 +.Dd December 23, 2011 .Dt TAR 5 .Os .Sh NAME diff --git a/Utilities/cmzlib/CMakeLists.txt b/Utilities/cmzlib/CMakeLists.txt index c42a43485..f161056e5 100644 --- a/Utilities/cmzlib/CMakeLists.txt +++ b/Utilities/cmzlib/CMakeLists.txt @@ -40,4 +40,4 @@ ENDFOREACH(name) ADD_LIBRARY(cmzlib ${ZLIB_SRCS}) -INSTALL(FILES Copyright.txt DESTINATION ${CMake_DOC_DEST}/cmzlib) +INSTALL(FILES Copyright.txt DESTINATION ${CMAKE_DOC_DIR}/cmzlib) diff --git a/Utilities/cmzlib/zlib.h b/Utilities/cmzlib/zlib.h index 022817927..46e2db490 100644 --- a/Utilities/cmzlib/zlib.h +++ b/Utilities/cmzlib/zlib.h @@ -869,7 +869,7 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not + the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ @@ -43,9 +43,9 @@ if [ "$cmake_version_tweak" != "0" ]; then cmake_version="${cmake_version}.${cmake_version_tweak}" fi -cmake_data_dir="/share/cmake-${cmake_version_major}.${cmake_version_minor}" -cmake_doc_dir="/doc/cmake-${cmake_version_major}.${cmake_version_minor}" -cmake_man_dir="/man" +cmake_data_dir="share/cmake-${cmake_version_major}.${cmake_version_minor}" +cmake_doc_dir="doc/cmake-${cmake_version_major}.${cmake_version_minor}" +cmake_man_dir="man" cmake_init_file="" cmake_bootstrap_system_libs="" cmake_bootstrap_qt_gui="" @@ -160,8 +160,8 @@ if ${cmake_system_mingw}; then fi elif ${cmake_system_haiku}; then cmake_default_prefix=`finddir B_COMMON_DIRECTORY` - cmake_man_dir="/documentation/man" - cmake_doc_dir="/documentation/doc/cmake-${cmake_version}" + cmake_man_dir="documentation/man" + cmake_doc_dir="documentation/doc/cmake-${cmake_version}" else cmake_default_prefix="/usr/local" fi @@ -247,7 +247,8 @@ CMAKE_CXX_SOURCES="\ cmMakefileUtilityTargetGenerator \ cmOSXBundleGenerator \ cmNewLineStyle \ - cmBootstrapCommands \ + cmBootstrapCommands1 \ + cmBootstrapCommands2 \ cmCommands \ cmTarget \ cmTest \ @@ -352,13 +353,13 @@ Configuration: Directory and file names: --prefix=PREFIX install files in tree rooted at PREFIX - [${cmake_default_prefix}] + ['"${cmake_default_prefix}"'] --datadir=DIR install data files in PREFIX/DIR - [/share/CMake] + ['"${cmake_data_dir}"'] --docdir=DIR install documentation files in PREFIX/DIR - [/doc/CMake] + ['"${cmake_doc_dir}"'] --mandir=DIR install man pages files in PREFIX/DIR/manN - [/man] + ['"${cmake_man_dir}"'] ' exit 10 } @@ -691,7 +692,10 @@ if ${cmake_system_linux}; then # avoid binutils problem with large binaries, e.g. when building CMake in debug mode # See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50230 if ${cmake_machine_parisc}; then - cmake_ld_flags="${LDFLAGS} -Wl,--unique=.text.*" + # if -O[s23] is given the effect is inverted, so do not use the flag then + if [ "`echo "${CXXFLAGS}" | sed -r '/^(.* )?(-O[s234])( .*)?$/s/.*/-Os/'`" != "-Os" ]; then + cmake_ld_flags="${LDFLAGS} -Wl,--unique=.text.*" + fi fi fi @@ -1082,6 +1086,8 @@ KWSYS_STL_HAS_ALLOCATOR_OBJECTS=0 KWSYS_CXX_HAS_SETENV=0 KWSYS_CXX_HAS_UNSETENV=0 KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=0 +KWSYS_CXX_HAS_UTIMENSAT=0 +KWSYS_CXX_HAS_UTIMES=0 KWSYS_CXX_HAS_CSTDDEF=0 KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS=0 KWSYS_CXX_HAS_MEMBER_TEMPLATES=0 @@ -1397,7 +1403,7 @@ cmake_report cmVersionConfig.h${_tmp} "#define CMake_VERSION_PATCH ${cmake_versi cmake_report cmVersionConfig.h${_tmp} "#define CMake_VERSION_TWEAK ${cmake_version_tweak}" cmake_report cmVersionConfig.h${_tmp} "#define CMake_VERSION \"${cmake_version}\"" cmake_report cmConfigure.h${_tmp} "#define CMAKE_ROOT_DIR \"${cmake_root_dir}\"" -cmake_report cmConfigure.h${_tmp} "#define CMAKE_DATA_DIR \"${cmake_data_dir}\"" +cmake_report cmConfigure.h${_tmp} "#define CMAKE_DATA_DIR \"/${cmake_data_dir}\"" cmake_report cmConfigure.h${_tmp} "#define CMAKE_BOOTSTRAP" # Regenerate configured headers @@ -1447,11 +1453,15 @@ for a in ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} ${KWSYS_CXX_SOURCES} ${KWSYS_C_ objs="${objs} ${a}.o" done -# Generate dependencies for cmBootstrapCommands.cxx -for file in `grep "#include.*cm[^.]*.cxx" "${cmake_source_dir}/Source/cmBootstrapCommands.cxx" | sed "s/.* \"\(.*\)\"/\1/"`; do - cmBootstrapCommandsDeps="${cmBootstrapCommandsDeps} `cmake_escape "${cmake_source_dir}/Source/$file"`" +# Generate dependencies for cmBootstrapCommands1.cxx +for file in `grep "#include.*cm[^.]*.cxx" "${cmake_source_dir}/Source/cmBootstrapCommands1.cxx" | sed "s/.* \"\(.*\)\"/\1/"`; do + cmBootstrapCommands1Deps="${cmBootstrapCommands1Deps} `cmake_escape "${cmake_source_dir}/Source/$file"`" +done +cmBootstrapCommands1Deps=`echo $cmBootstrapCommands1Deps` +for file in `grep "#include.*cm[^.]*.cxx" "${cmake_source_dir}/Source/cmBootstrapCommands2.cxx" | sed "s/.* \"\(.*\)\"/\1/"`; do + cmBootstrapCommands2Deps="${cmBootstrapCommands2Deps} `cmake_escape "${cmake_source_dir}/Source/$file"`" done -cmBootstrapCommandsDeps=`echo $cmBootstrapCommandsDeps` +cmBootstrapCommands2Deps=`echo $cmBootstrapCommands2Deps` if [ "x${cmake_ansi_cxx_flags}" != "x" ]; then cmake_cxx_flags="${cmake_ansi_cxx_flags} ${cmake_cxx_flags}" @@ -1466,7 +1476,13 @@ if [ "x${cmake_cxx_flags}" != "x" ]; then fi cmake_c_flags_String="-DKWSYS_STRING_C" -cmake_cxx_flags_SystemTools="-DKWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV} -DKWSYS_CXX_HAS_UNSETENV=${KWSYS_CXX_HAS_UNSETENV} -DKWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=${KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H}" +cmake_cxx_flags_SystemTools=" + -DKWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV} + -DKWSYS_CXX_HAS_UNSETENV=${KWSYS_CXX_HAS_UNSETENV} + -DKWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=${KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H} + -DKWSYS_CXX_HAS_UTIMENSAT=${KWSYS_CXX_HAS_UTIMENSAT} + -DKWSYS_CXX_HAS_UTIMES=${KWSYS_CXX_HAS_UTIMES} +" cmake_c_flags="${cmake_c_flags}-I`cmake_escape \"${cmake_bootstrap_dir}\"` -I`cmake_escape \"${cmake_source_dir}/Source\"` \ -I`cmake_escape \"${cmake_bootstrap_dir}\"`" cmake_cxx_flags="${cmake_cxx_flags} -I`cmake_escape \"${cmake_bootstrap_dir}\"` -I`cmake_escape \"${cmake_source_dir}/Source\"` \ @@ -1478,7 +1494,8 @@ for a in ${CMAKE_CXX_SOURCES}; do echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" done -echo "cmBootstrapCommands.o : $cmBootstrapCommandsDeps" >> "${cmake_bootstrap_dir}/Makefile" +echo "cmBootstrapCommands1.o : $cmBootstrapCommands1Deps" >> "${cmake_bootstrap_dir}/Makefile" +echo "cmBootstrapCommands2.o : $cmBootstrapCommands2Deps" >> "${cmake_bootstrap_dir}/Makefile" for a in ${CMAKE_C_SOURCES}; do src=`cmake_escape "${cmake_source_dir}/Source/${a}.c"` echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" @@ -1511,14 +1528,6 @@ set (CMAKE_MAN_DIR "'"${cmake_man_dir}"'" CACHE PATH "Install location for man p set (CMAKE_DATA_DIR "'"${cmake_data_dir}"'" CACHE PATH "Install location for data (relative to prefix)." FORCE) ' > "${cmake_bootstrap_dir}/InitialCacheFlags.cmake" -# Suppress -isysroot if user-provided flags already have it. -if echo "${cmake_c_flags}" | grep isysroot >/dev/null 2>&1 && - echo "${cmake_cxx_flags}" | grep isysroot >/dev/null 2>&1; then - echo ' -set(CMAKE_OSX_SYSROOT "" CACHE PATH "" FORCE) -' >> "${cmake_bootstrap_dir}/InitialCacheFlags.cmake" -fi - # Add configuration settings given as command-line options. if [ "x${cmake_bootstrap_qt_gui}" != "x" ]; then echo ' |