Что вы видите, это последствия новой функции PowerShell v5. Format-Table
теперь собирают ввод в течение 300 миллисекунд, чтобы найти лучшую ширину столбца. Он работает таким образом, даже если вы явно указали -AutoSize:$false
.
Когда вы вводите команду в командной строке, эта команда неявно передается в один экземпляр команды Out-Default
. Затем команда Out-Default
определяет, как форматировать объекты и печатать их на хосте (консоли) PowerShell. Таким образом, даже если вы не используете Format-Table
непосредственно в своем коде, это не означает, что у вас нет Format-Table
в вашем конвейере. Out-Default
может решить форматировать объекты как таблицу и использовать Format-Table
внутренне.
Пользовательские объекты с четырьмя или менее свойствами и без специального форматирования, определенные для них в файлах формата, отформатированы как таблица. Используя Select-Object
с двумя свойствами, вы создаете именно эти объекты.
Конвейер PowerShell является однопоточным. Это означает, что Format-Table
не может просто выводить все собранные объекты, когда прошло интервал в 300 миллисекунд. Format-Table
должны ждать, пока вы не нанесете на него следующий элемент (вызванный процесс) или конец сообщенного конвейера (вызванный конечный блок).
PS> Get-NetAdapter | Select-Object Name,Status
>>> Pause
>>> [PSCustomObject]@{Name='Some long name';Status='Some long status'} #1
>>> Pause
>>> [PSCustomObject]@{Name='Even longer name';Status='Even longer status'}
>>> Pause
Press Enter to continue...:
Name Status
---- ------
Ethernet Up
Some long name Some long status
Press Enter to continue...:
Even longer... Even longer s...
Press Enter to continue...:
PS>
Неявный Format-Table
ничего не печатает (строго говоря он печатает пустую строку) перед первым Pause
, потому что он все еще ждет больше входных объектов (еще 300 миллисекунд), чтобы определить ширину столбца. Когда первый объект (# 1) приходит через интервал 300 миллисекунд (при условии, что вы не должны нажимать клавишу Enter), тогда Format-Table
выбирает ширину столбца и печатает все собранные объекты. Любые другие объекты будут напечатаны без задержки, но они больше не могут влиять на ширину столбца. Если значение является большим для столбца, оно будет усечено.
PS> Get-NetAdapter | Select-Object Name,Status | Format-Table
>>> Pause
Name Status
---- ------
Ethernet Up
Press Enter to continue...:
PS>
С помощью этого кода до Format-Table
будет выполнен конечный блок явного Format-Table
. В конце блока Format-Table
известно, что он уже получил все входные данные, поэтому он может выбирать ширину столбца и сразу выводить все собранные объекты. Неявные Out-Default
видят, что объекты форматирования из выхода Format-Table
и Out-Default
знают, что им не требуется форматирование добавок и их печать на хосте (консоли) сразу же. Итак, вся таблица была напечатана до Pause
.
Обратите внимание на разницу в размещении конца метки таблицы (две пустые строки). В первом примере он помещается после последнего Pause
. Это потому, что неявный Format-Table
все еще активен и все еще ждет, что вы передаете ему дополнительный объект. Только когда ваша команда полностью завершена Format-Table
, подтвердите завершение ввода и вывода конца таблицы. Во втором примере явная Format-Table
завершается до Pause
, поэтому вся таблица (включая конец таблицы) печатается перед командой Pause
.
Разница в размещении конца метки таблицы может быть заметил и предыдущие версии PowerShell.
Даже не идите туда. Предварительно скомпилированные заголовки означают это каждый раз, когда одно из изменений заголовков, необходимо восстановить все . Вы удачливы, если у Вас есть система сборки, которая понимает это. Чаще, чем никогда, Ваша сборка просто перестанет работать, пока Вы не поймете изменение чего-то, что предварительно компилируется, и поэтому необходимо сделать, полное восстанавливает. Можно избежать этого главным образом путем предварительной компиляции заголовков, что Вы абсолютно положительны, не изменится, но тогда Вы бросаете значительную часть выигрыша в быстродействии также.
другая проблема состоит в том, что Ваше пространство имен загрязнено всеми видами символов, которые Вы не знаете или заботитесь о во многих местах, где Вы использовали бы предварительно скомпилированные заголовки.
Вот фрагмент кода, чтобы позволить Вам использовать предварительно скомпилированный заголовок для своего проекта. Добавьте следующее к своему CMakeLists.txt, заменяющему myprecompiledheaders
и myproject_SOURCE_FILES
как соответствующее:
if (MSVC)
set_source_files_properties(myprecompiledheaders.cpp
PROPERTIES
COMPILE_FLAGS "/Ycmyprecompiledheaders.h"
)
foreach( src_file ${myproject_SOURCE_FILES} )
set_source_files_properties(
${src_file}
PROPERTIES
COMPILE_FLAGS "/Yumyprecompiledheaders.h"
)
endforeach( src_file ${myproject_SOURCE_FILES} )
list(APPEND myproject_SOURCE_FILES myprecompiledheaders.cpp)
endif (MSVC)
Что ж, когда сборки на четырехъядерном компьютере занимают более 10 минут каждый раз, когда вы меняете одну строку в любом из файлов проекта, это говорит о том, что пора добавить предварительно скомпилированные заголовки для окон. На * nux я бы просто использовал ccache и не беспокоился об этом.
Я реализовал в своем основном приложении несколько библиотек, которые оно использует. Это прекрасно работает на данный момент. Также необходимо создать исходный файл и заголовочный файл pch и включить в исходный файл все заголовки, которые вы хотите предварительно скомпилировать. Я делал это в течение 12 лет с MFC, но мне потребовалось несколько минут, чтобы вспомнить это ..
Я использую следующий макрос для генерации и использования предварительно скомпилированных заголовков:
MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar)
IF(MSVC)
GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
SET(PrecompiledBinary "${CMAKE_CURRENT_BINARY_DIR}/${PrecompiledBasename}.pch")
SET(Sources ${${SourcesVar}})
SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_OUTPUTS "${PrecompiledBinary}")
SET_SOURCE_FILES_PROPERTIES(${Sources}
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeader}\" /FI\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_DEPENDS "${PrecompiledBinary}")
# Add precompiled header to SourcesVar
LIST(APPEND ${SourcesVar} ${PrecompiledSource})
ENDIF(MSVC)
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)
Допустим, у вас есть переменная $ {MySources} со всеми вашими исходными файлами, код, который вы хотели бы использовать, будет просто be
ADD_MSVC_PRECOMPILED_HEADER("precompiled.h" "precompiled.cpp" MySources)
ADD_LIBRARY(MyLibrary ${MySources})
Код все равно будет нормально работать и на платформах, отличных от MSVC. Довольно аккуратно :)
В итоге я использовал адаптированную версию макроса larsm. Использование $ (IntDir) в качестве пути к pch позволяет разделить предварительно скомпилированные заголовки для отладочных и выпускных сборок.
MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar)
IF(MSVC)
GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
SET(PrecompiledBinary "$(IntDir)/${PrecompiledBasename}.pch")
SET(Sources ${${SourcesVar}})
SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_OUTPUTS "${PrecompiledBinary}")
SET_SOURCE_FILES_PROPERTIES(${Sources}
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeader}\" /FI\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_DEPENDS "${PrecompiledBinary}")
# Add precompiled header to SourcesVar
LIST(APPEND ${SourcesVar} ${PrecompiledSource})
ENDIF(MSVC)
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)
ADD_MSVC_PRECOMPILED_HEADER("stdafx.h" "stdafx.cpp" MY_SRCS)
ADD_EXECUTABLE(MyApp ${MY_SRCS})
Адаптировано из Дейва, но более эффективно (устанавливает целевые свойства, а не для каждого файла):
if (MSVC)
set_target_properties(abc PROPERTIES COMPILE_FLAGS "/Yustd.h")
set_source_files_properties(std.cpp PROPERTIES COMPILE_FLAGS "/Ycstd.h")
endif(MSVC)